如果我尝试迭代切片两次,the JSON API specification:
let a = &[1, 2, 3];
for i in a {
println!("{}", i);
}
for i in a { // works fine
println!("{}", i);
}
如果我尝试两次迭代一个向量,it works fine:
let a = vec![1, 2, 3];
for i in a {
println!("{}", i);
}
for i in a {
println!("{}", i);
}
error[E0382]: use of moved value: `a`
--> src/main.rs:6:14
|
3 | for i in a {
| - value moved here
...
6 | for i in a {
| ^ value used here after move
|
= note: move occurs because `a` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
我看到it fails特征按值self
获取,因此第二个示例失败对我来说很有意义。为什么第一个例子成功?
答案 0 :(得分:21)
就像你说的那样,for
通过接受你要求它迭代的事物来工作,并通过IntoIterator::into_iter
传递它以产生实际的迭代器值。同样如你所说,into_iter
将主题按值。
因此,当您尝试直接迭代Vector
时,这意味着您将整个向量按值传递到其IntoIterator
实现中,从而消耗了向量进行中。这就是为什么你不能直接迭代一个向量两次:第一次使用它迭代它,之后它就不再存在了。
然而,切片是不同的:切片是一个不可变的,借用的指向其数据的指针;不可变的,借来的指针可以自由复制。这意味着不可变切片的IntoIterator
只是借用数据而不消耗它(不是它可以)。或者,从另一个角度来看,它的IntoIterator
实现只是获取切片的副本,而您无法复制Vec
。
应该注意的是,您可以通过迭代借用来迭代Vec
,而无需消费它。如果您选中documentation for Vec
,则会注意到它会列出IntoIterator
,Vec<T>
和&Vec<T>
的{{1}}实施。
&mut Vec<T>