在迭代时修改结构是否有优雅的解决方案?

时间:2015-03-28 21:39:00

标签: rust

我正在尝试构建迭代时更改的点向量:

struct Point {
    x: i16,
    y: i16,
}

fn main() {
    let mut points: Vec<Point> = vec![];
    // unsure if point is mutable
    points.push(Point { x: 10, y: 10 });
    // thus trying it explicitly
    let mut p1 = Point { x: 20, y: 20 };
    points.push(p1);

    for i in points.iter() {
        println!("{}", i.x);
        i.x = i.x + 10;
    }
}

编译时,我收到错误:

error[E0594]: cannot assign to immutable field `i.x`
  --> src/main.rs:16:9
   |
16 |         i.x = i.x + 10;
   |         ^^^^^^^^^^^^^^ cannot mutably borrow immutable field

当我学习here时,Rust不允许在迭代时修改结构,从而导致错误。

如何以优雅的方式修改它?如果我阅读this answer并正确使用,那么我会想到以下内容:

  1. 从向量中弹出项目,修改它并将其推回。
  2. 创建一个临时结构,我将更改的项目推送到原始结构并用循环外的临时结构替换(如何?)。
  3. 虽然我认为我可以(1)工作,但我并不是真的很高兴所有这些流行音乐和推动(无论如何这是高性能吗?)。关于(2),我不知道如何使它工作 - 如果这可以工作。

    问题:

    1. 是(2)解决方案,如果是,它会是什么样子?
    2. 还有其他解决方案吗?
    3. 不同解决方案的优点或缺点是什么,特别是在性能方面?

1 个答案:

答案 0 :(得分:17)

您无法修改正在迭代的结构,即向量points。但是,修改从迭代器获得的元素是完全没有问题的,你只需要选择变为可变性:

for i in points.iter_mut() {

或者,使用更现代的语法:

for i in &mut points {

可变性是选择性的,因为迭代进行迭代会进一步限制在迭代时使用points可以执行的操作。由于可变别名(即指向同一存储器的两个或多个指针,其中至少有一个是&mut)被禁止,因此您无法从points 读取 iter_mut()迭代器就在附近。