就像下面的rust代码:while
循环编译并运行良好,但for iter
版本由于错误而无法编译:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:22:9
|
20 | for i in v.iter() {
| --------
| |
| immutable borrow occurs here
| immutable borrow later used here
21 | println!("v[i]: {}", i);
22 | v.push(20);
| ^^^^^^^^^^ mutable borrow occurs here
error: aborting due to previous error
字符串
但据了解,while
循环也有相同的情况,len
和get
也借用不变,为什么它不冲突与push
作为借用可变?请告诉我,我的理解错过了这里,非常感谢的启发!
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
let mut i = 0;
while i < v.len() && i < 10 {
v.push(20);
println!("v[i]: {:?}", v.get(i));
i += 1;
}
// for i in v.iter() {
// println!("v[i]: {}", i);
// v.push(20);
// }
}
型
3条答案
按热度按时间jtjikinw1#
代码的
for
版本大致相当于以下内容:字符串
Playground
如果你试图编译它,你会得到一个错误,也许更有意义一点:
型
迭代器在整个循环期间不可变地借用
v
,因此在循环内不能进行任何可变借用。当然,即使你能做到这一点,你最终会得到一个无限循环,因为你不断追加另一个项目。
w80xi6nr2#
简单地说,当您调用
.iter()
时,您将创建一个新对象(一个迭代器),它借用你的向量(不可变),并且the一个接一个地给出元素,这意味着你实际上借用了v
整个循环时间。另一方面,当你通过.get(i)
访问它时,你直接从vector中借用一个元素,所以当你push
的时候它就不受借用的限制了。这种限制的原因很简单:假设实际的
for
循环编译了,它将永远运行。(为了防止在while
循环中出现这种情况,您必须添加人工条件i<10
!),而这显然不是预期的目标(或者如果是的话,你显然会做其他的事情,例如使用while let
或loop
语句),Rust试图防止你“开枪打自己的腿”,因为你真的不知道如何做你想做的事情,并尝试错误的方式。要做你想做的事,你可以做:
字符串
因为
v.len()
调用在整个for
循环的时间内不借用v
,而是仅在开始时借用。lmyy7pcs3#
Rust borrow checker定义了一组规则,以确定可以借用哪些模式(可变或不可变)。它甚至做得更多,即处理生命周期,如果你不借用,你就移动。
对于有抱负的Rust程序员来说,处理借用检查器强加的规则是痛苦之谷(又名学习曲线),他们必须通过才能变得富有成效。
一旦迭代器不可变地借用了向量(并在循环期间保持它),借用检查器就会抱怨尝试变异。
如果你是一个横向思考者,就像我一样......每当我看到一种新语言的东西,我不能完全理解我的头,我试着用一种我已经更了解的语言写一个教育性的近似“奇怪的东西”。
所以,希望它能有所帮助,你可以找到一个非常简化和大胆的近似rust在C中的行为(在编译时)。只是-在我的C代码中,它发生在运行时,违反规则会导致抛出异常。
我们使用的示例的“状态”(在本例中为
std::vector<int32_t>
),关于可变性以及根据我们匆忙发明的借用规则集我们仍然可以做什么(可能与 rust 病相似,也可能不相似)由不同的类型表达(Managed<T>::ConstRef
或Managed<T>::MutableRef
)。状态应用的范围是lambda函数的范围,下面代码中的main()
试图复制for i in vec.iter() { .. }
场景。也许从这个Angular 看问题对某人有帮助。
字符串