如何在向量的元素上运行for循环,并在rust中在for循环内和for循环外更改向量?

Pan*_*ute 1 for-loop move ownership rust borrow-checker

我是Rust的新手。我需要在for循环之前创建一个向量。运行循环。在for循环内更改向量。然后在for循环之后更改向量。

我尝试了以下代码,并尝试使用不可变借位,但两者均无效。

fn main() {
    let mut vec1 = vec![4, 5];
    vec1.push(6);
    for i in vec1 {
        if i % 2 == 0 {
            vec1.push(7);
        }
    }
    vec1.push(8);
    println!("vec1={:?}", vec1);
}
Run Code Online (Sandbox Code Playgroud)

我希望在for循环内和之后编译和更改向量。但它显示此错误消息:

fn main() {
    let mut vec1 = vec![4, 5];
    vec1.push(6);
    for i in vec1 {
        if i % 2 == 0 {
            vec1.push(7);
        }
    }
    vec1.push(8);
    println!("vec1={:?}", vec1);
}
Run Code Online (Sandbox Code Playgroud)

您能解释为什么会发生移动吗?你可以编译吗?

Luk*_*odt 5

您的代码有两个问题。幸运的是,通过更改一件事,它们都可以解决。问题是:

  • 写入for _ in vec1会将值vec1移入循环。就像其他所有动作一样,这意味着循环后无法访问该值!如果您需要有关所有权和搬迁的复习,请阅读Rust书中的相关章节。您可以通过遍历对向量元素的引用for _ in &vec1
  • 您正在尝试对要迭代的向量进行变异。无论您是按值(按您的方式)还是按引用遍历向量,都不能在遍历向量的同时更改向量。这有很多充分的理由!在您的情况下,如果在迭代时添加元素,则很容易导致无限循环。

为了同时解决这两个问题,您可以遍历索引到向量而不是向量元素(Playground):

let mut vec1 = vec![4, 5];
vec1.push(6);
for i in 0..vec1.len() {
    if vec1[i] % 2 == 0 {
        vec1.push(7);
    }
}
vec1.push(8);
println!("vec1={:?}", vec1);
Run Code Online (Sandbox Code Playgroud)

这样,向量不会被for循环移动或借用,我们可以在循环期间和循环之后自由对其进行突变。此特定解决方案迭代原始矢量的索引,这意味着循环中不会迭代循环中添加的元素。这是避免意外无限循环的良好保护。但是请注意,您仍然可以通过例如在迭代过程中从向量中删除元素来射击自己。通常,独立于编程语言,对集合进行迭代时对其进行变异是危险的,应谨慎进行。