在Rust by Example中,它说:
在作业左侧借用
ref
相当于在右侧借用&
。
我认为这两个for
循环将是等效的:
编译成功:
let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
*i = *i + 1;
}
println!("{:?}", v2);
不编译:
let mut v1 = vec![1, 2, 3];
for ref mut i in v1 {
*i = *i + 1;
}
println!("{:?}", v1);
似乎v
已移动:
error[E0382]: use of moved value: `v1`
--> src/main.rs:6:22
|
3 | for ref mut i in v1 {
| -- value moved here
...
6 | println!("{:?}", v1);
| ^^ value used here after move
|
= note: move occurs because `v1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
答案 0 :(得分:3)
您从书中引用的是正常作业的规则,例如let
的作业。例如:
let x = &42;
let ref x = 42;
但是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
循环情况下,ref
和&
是不相等的。
在循环右侧使用&
时,它不会直接更改变量的绑定;您只需更改要迭代的对象的类型。然后,一切都归结到IntoIterator
的{{1}}实现和Vec<_>
的实现。
&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>
类型的值。结论是,在&mut T
循环中使用ref
可能不太有用。