如果我尝试迭代两次切片,它可以正常工作:
let a = &[1, 2, 3]; for i in a { println!("{}", i); } for i in a { // works fine println!("{}", i); }
如果我尝试迭代向量两次,它会失败:
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`, which does not implement the `Copy` trait
我看到IntoIterator
特征是self
按值获取的,所以我觉得第二个例子失败了.为什么第一个例子成功了?
就像你说的那样,for
通过接受你要求它迭代的东西,然后传递它IntoIterator::into_iter
来产生实际的迭代器值.正如你所说,按价值into_iter
取得主题.
因此,当您尝试Vector
直接迭代a时,这意味着您将整个向量按值传递到其IntoIterator
实现中,从而消耗了流程中的向量.这就是为什么你不能直接迭代一个向量两次:第一次使用它迭代它,之后它就不再存在了.
但是,切片是不同的:切片是指向其数据的不可变的,借用的指针; 不可变的,借来的指针可以自由复制.这意味着IntoIterator
for immutable slice只是借用数据而不消耗它(不是它可以).或者,以另一种方式来看,它的IntoIterator
实现只是取一个切片的副本,而你不能复制一个Vec
.
应该注意的是,您可以通过遍历借位来迭代a Vec
而不消耗它.如果您检查文档Vec
,你会注意到它列出的实现IntoIterator
了Vec
,&Vec
和&mut Vec
.
let mut a: Vec= vec![1, 2, 3]; for i in &a { // iterate immutably let i: &i32 = i; // elements are immutable pointers println!("{}", i); } for i in &mut a { // iterate mutably let i: &mut i32 = i;// elements are mutable pointers *i *= 2; } for i in a { // iterate by-value let i: i32 = i; // elements are values println!("{}", i); } // `a` no longer exists; it was consumed by the previous loop.