首页 > 解决方案 > 当向量中的每个项目需要所述向量中的所有其他项目时的所有权

问题描述

我对 Rust 很陌生,在这种情况下我无法弄清楚如何处理所有权(和生命周期?)。我对编程并不陌生,实际上我正在重新实现已经在 J​​S 中工作的东西(https://sheraff.github.io/boids/)。


在这种情况下,Universe基本上是一个包含许多Entity. 在每个 上universe.tick(),每个人都Entity需要知道Entity它可以“看到”哪个其他人。为此,entity.update()将列表Entity作为参数。

结果,我有一段脚本,我似乎无法找到一个好的所有权结构:

for mut entity in self.entities {
    entity.update(&self.entities);
}

你会怎么做?

我可以告诉你我尝试了什么,但感觉就像我已经尝试了我能想到的一切,包括阅读 Rust 书,并且我已经收到了所有可能的错误消息......对不起。


PS:当然,及时,它不是要传入的整个实体列表,entity.update而是一个过滤列表。


下面是代码结构的一般简化:

pub struct Entity {
    pub point: Point,
    vision: Cone,
    angle: Angle
}
impl Entity {
    pub fn update(&mut self, entities: &Vec<Entity>) {
        // ...
    }
}

pub struct Universe {
    pub entities: Vec<Entity>
}
impl Universe {
    pub fn new() -> Universe {
        let mut entities: Vec<Entity> = vec![];
        for _ in 1..200 {
            let mut entity = Entity::new();
            entities.push(entity);
        }

        Universe {
            entities
        }
    }

    pub fn tick(&self) {
        for mut entity in self.entities {
            entity.update(&self.entities);
        }
    }
}

标签: rustownership

解决方案


如果每个实体都需要了解每个实体,那么似乎不是实体负责更新。您可能应该从实体上的方法重构为对所有实体进行操作的函数。

在嵌套循环中迭代实体有点困难。一种解决方案是遍历数组的一个副本并允许另一个循环获取可变引用。

pub fn update_entities(entities: &mut Vec<Entity>) {
    for a in entities.clone() {
        for mut entity in entities.iter_mut() {
            if entity.id == a.id { // If you can compare them, otherwise use indexed for loop and compare indices.
                continue;
            }
            // Do stuff.
        }
    }
}

您需要复制的原因是因为 Rust 的黄金法则:您可以拥有一个可变引用任意数量的不可变引用。嵌套的 for 循环打破了这一规则,因为您需要一个可变引用和一个不可变引用。


推荐阅读