一个数组如何包含对同一对象的多个可变引用?

时间:2019-01-10 23:25:26

标签: rust

我正在制作一款基于图块的游戏,其结构跨越了多个图块。结构下的每个图块都必须具有对该结构的可变引用。对于跨越两个图块的结构,表示地图的2D数组必须同时包含对该结构的两个可变引用。

我还有一个可变地拥有我所有结构的列表(用于迭代)

我用&mut尝试了此操作,但失败了:

let mut all_structures: Vec<Box<Structure>> = Vec::new();
let mut grid: [[Vec<&mut Box<Structure>>; 4]; 4] = Default::default(); // accessed [y][x]

let mut house: Box<Structure> = Box::new(House { });
grid[1][1].push(&mut house);
grid[1][2].push(&mut house);
all_structures.push(house);

有错误:

error[E0499]: cannot borrow `house` as mutable more than once at a time
  --> src/main.rs:21:21
   |
20 |     grid[1][1].push(&mut house);
   |                     ---------- first mutable borrow occurs here
21 |     grid[1][2].push(&mut house);
   |                ---- ^^^^^^^^^^ second mutable borrow occurs here
   |                |
   |                first borrow later used by call

现在这只是单线程,因此没有什么是线程安全的

我将代码放在playground

1 个答案:

答案 0 :(得分:2)

最简单的选择是使用Rc<RefCell<Structure>>而不是Box<Structure>

Rc<T>支持类型为T的值的共享所有权,通过自动生存期管理,您可以拥有多个指向同一对象的指针。 Rc<T>不是线程安全的;如果以后发现需要线程安全,则可以改为使用Arc

RefCell<T>允许您在运行时而不是在编译时强制执行Rust借用规则(即可以有一个&mut借用或任意数量的&借用) :这意味着可以有多个路径,只要您实际上不这样做,就可以通过该路径来变异同一对象。

我在playground上举了一个完整的例子。请注意,这会使用.borrow().borrow_mut(),如果您实际上违反了借用规则(例如,一次可变地多次借用相同的Structure),则会感到恐慌。