为什么我可以遍历一个切片两次,而不是一个向量? [英] Why can I iterate over a slice twice, but not a vector?

查看:35
本文介绍了为什么我可以遍历一个切片两次,而不是一个向量?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如果我尝试对切片进行两次迭代,它工作正常:

If I try to iterate over a slice twice, it works fine:

let a = &[1, 2, 3];
for i in a {
    println!("{}", i);
}
for i in a {            // works fine
    println!("{}", i);
}

如果我尝试对向量进行两次迭代,它失败:

If I try to iterate over a vector twice, it fails:

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

我看到 IntoIterator trait 接受 self 的值,所以对我来说第二个例子失败是有道理的.为什么第一个例子会成功?

I see that the IntoIterator trait takes self by value, so it makes sense to me that the second example fails. Why does the first example succeed?

推荐答案

就像你说的,for 的工作原理是将你要求它迭代的事物它通过 IntoIterator::into_iter 生成实际迭代器值.同样如您所说,into_iter为主题.

Like you said, for works by taking the thing you asked it to iterate over, and passing it through IntoIterator::into_iter to produce the actual iterator value. Also as you said, into_iter takes the subject by value.

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

So, when you try to iterate over a Vector directly, this means you pass the entire vector, by value, into its IntoIterator implementation, thus consuming the vector in the process. Which is why you can't iterate over a vector directly twice: iterating over it the first time consumes it, after which it no longer exists.

然而,切片是不同的:切片是一个不可变的、借用的指向其数据的指针;不可变的、借用的指针可以自由复制.这意味着用于不可变切片的 IntoIterator 只是借用数据而不使用它(不是它可以).或者,换个角度来看,它的 IntoIterator 实现只是获取切片的副本,而您不能复制 Vec.

However, slices are different: a slice is an immutable, borrowed pointer to its data; immutable, borrowed pointers can be copied freely. This means that the IntoIterator for immutable slices just borrows the data and doesn't consume it (not that it could). Or, to look at it another way, its IntoIterator implementation is simply taking a copy of the slice, whereas you can't copy a Vec.

应该注意的是,您可以通过迭代借用来迭代 Vec 而无需消耗它.如果您查看 Vec 的文档,你会注意到它列出了 Vec&Vec& 的 IntoIterator 的实现;mut Vec.

It should be noted that you can iterate over a Vec without consuming it by iterating over a borrow. If you check the documentation for Vec, you'll note that it lists implementations of IntoIterator for Vec<T>, &Vec<T> and &mut Vec<T>.

let mut a: Vec<i32> = 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.

这篇关于为什么我可以遍历一个切片两次,而不是一个向量?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆