为什么通过 `for` 循环迭代集合在 Rust 中被认为是一种“移动”操作?

11

我有以下 Rust 程序。

fn main() {
    let v = vec![100, 32, 57];
    for i in v {
        println!("{}", i);
    }

    println!("{:?}", v);
}

运行时我得到了:

error[E0382]: borrow of moved value: `v`
 --> src\main.rs:7:22
  |
2 |     let v = vec![100, 32, 57];
  |         - move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |     for i in v {
  |              -
  |              |
  |              value moved here
  |              help: consider borrowing to avoid moving into the for loop: `&v`
...
7 |     println!("{:?}", v);
  |                      ^ value borrowed here after move

错误说明在for i in v发生了一个move,但我只是在使用由let v = vec![100, 32, 57]定义的同一变量v。这不像是let v2 = v; for i in v2 ...那样,将值从v移动到v2。能否有人帮忙解释一下?
2个回答

18
根据https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops所述, for表达式是一个语法结构,用于循环遍历由std::iter::IntoIterator实现提供的元素。 Vec实现了IntoIterator,允许通过消费它来拥有Vec实例的元素: 创建一个消费迭代器, 即一个将向量中的每个值(从 start 到 end)移动出来的迭代器。调用此方法后,向量不能再被使用。 (正如错误信息所指出的那样,修复这个问题的方法是循环遍历&v而不是v,借用它的元素而不是拥有它们。你可以循环遍历for &i in &v以保持i的类型。) 在高层次上,你拥有v的元素似乎是不必要的,因为它们是可复制的,但这里没有特殊的实现允许使用该信息。 IntoIterator.into_iter()采用self, 这意味着for循环总是消耗被迭代的值。

1

如其他答案所述,for item in container { ... } 调用 container.into_iter(),它会消耗容器(通过值传递)并返回一个 IntoIter 迭代器,该迭代器拥有项目直到循环完成。

一种在不消耗项目的情况下循环遍历项目的方法是使用对容器的引用:

let container: Vec<String> = vec!["Hello".to_string(), "World".to_string()];
for item in &container {
    println!("item: {item}");
}
println!("container: {container:?}");

另一种方法是使用 for item in container.iter() { ... },调用 iter() 而不是隐式的 into_iter() 方法:

let container: Vec<String> = vec!["Hello".to_string(), "World".to_string()];
for item in container.iter() {
    println!("item: {item}");
}
println!("container: {container:?}");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接