为什么我可以迭代两次切片,但不能迭代?

时间:2016-01-03 02:37:18

标签: rust

如果我尝试迭代切片两次,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获取,因此第二个示例失败对我来说很有意义。为什么第一个例子成功?

1 个答案:

答案 0 :(得分:21)

就像你说的那样,for通过接受你要求它迭代的事物来工作,并通过IntoIterator::into_iter传递它以产生实际的迭代器值。同样如你所说,into_iter将主题按值

因此,当您尝试直接迭代Vector时,这意味着您将整个向量按值传递到其IntoIterator实现中,从而消耗了向量进行中。这就是为什么你不能直接迭代一个向量两次:第一次使用它迭代它,之后它就不再存在了。

然而,切片是不同的:切片是一个不可变的,借用的指向其数据的指针;不可变的,借来的指针可以自由复制。这意味着不可变切片的IntoIterator只是借用数据而不消耗它(不是它可以)。或者,从另一个角度来看,它的IntoIterator实现只是获取切片的副本,而您无法复制Vec

应该注意的是,您可以通过迭代借用来迭代Vec ,而无需消费它。如果您选中documentation for Vec,则会注意到它会列出IntoIteratorVec<T>&Vec<T>的{​​{1}}实施。

&mut Vec<T>