Why is `ref mut` on a for loop binding not the same as `&mut` on the variable being looped over?

wli*_*iao 2 rust

In Rust by Example, it says:

A ref borrow on the left side of an assignment is equivalent to an & borrow on the right side.

I thought these two for loops would be equivalent:

Compiles successfully:

let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
    *i = *i + 1;
}
println!("{:?}", v2);
Run Code Online (Sandbox Code Playgroud)

Does not compile:

let mut v1 = vec![1, 2, 3];
for ref mut i in v1 {
    *i = *i + 1;
}
println!("{:?}", v1);
Run Code Online (Sandbox Code Playgroud)

It seems v is moved:

let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
    *i = *i + 1;
}
println!("{:?}", v2);
Run Code Online (Sandbox Code Playgroud)

rod*_*igo 5

你从书中引用的是正常作业的规则,例如由let. 例如:

let x = &42;
let ref x = 42;
Run Code Online (Sandbox Code Playgroud)

但是for循环中的名称绑定有点不同:

  • 要循环的值被转换为迭代器( <v1 as IntoIterator>::into_iter()) 让我们调用它的结果it
  • 然后it.next()反复调用:
    • 如果它返回,Some(_)则该值绑定到您的变量。就像你写的一样let Some(ref mut i) = it.next()let Some(mut i) = it.next()。这就是问题所在ref
    • 如果它返回None循环结束。

所以在for循环的情况下, theref和 the&是不等价的。

当你&在循环的右边使用时,它不会直接改变变量的绑定;您只需更改迭代对象的类型。然后,一切都归结为IntoIteratorforVec<_>与 for 的实现&Vec<_>

  • 如果您迭代Vec<T>,它将获得向量的所有权并且迭代返回值本身。因此for i in v1消耗向量并且i具有包含值的类型T
  • 如果您迭代&Vec<T>,它会借用向量并且迭代返回指向所包含值的指针&T,因此在for i in &v1类型中i实际上是指向值的指针。可以得到同样的效果for i in v1.iter()
  • 如果您迭代&mut Vec<T>, 就像前一个一样,但可变,因此迭代返回 type 的值&mut T

结论是reffor循环中使用可能不是那么有用。