了解循环中的不可变借用

时间:2019-09-04 11:31:18

标签: rust borrow-checker

我不太明白为什么会这样编译:

fn main() {
    let mut v = vec![1,2,3];

    for i in 1..v.len() {
            v[i] = 20;
    }
}

...但不是:

fn main() {
    let mut v = vec![1,2,3];

    for (i,_) in v.iter().enumerate() {
            v[i] = 20;
    }
}

错误:

error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
 --> src/main.rs:6:13
  |
4 |     for (i,_) in v.iter().enumerate() {
  |                  --------------------
  |                  |
  |                  immutable borrow occurs here
  |                  immutable borrow later used here
5 | 
6 |             v[i] = 20;
  |             ^ mutable borrow occurs here

在两种情况下,我们都是不可变的借贷(一种是在调用len()时借用,另一种是在我们调用iter()时借用)。

因此,我的期望是不应该编译第一个代码段-当存在不可变的借位时,我们在进行分配时要进行可变的借位。

我误会什么?

1 个答案:

答案 0 :(得分:7)

在第一种情况下,您实际上并不是在进行一成不变的借用,或者说,它在对len()的调用返回后终止(因为len返回的原始类型不包含对其的引用使用)。这意味着您的循环非常完美,因为您拥有一个唯一的可变对象。

在第二个上,您要创建一个实现Iterator<Item = &u32>的类型,然后在该迭代器上进行迭代。迭代器对您的集合有不可变的借用(否则您怎么能对它调用next()?)。这有点隐蔽,但这就是不变的借贷所在,以及为什么您不能做自己做的事情。

通常,在使用迭代器时,当您需要修改要迭代的元素时,iter_mut是显而易见的原因:-)