我正在制作一款基于图块的游戏,其结构跨越了多个图块。结构下的每个图块都必须具有对该结构的可变引用。对于跨越两个图块的结构,表示地图的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
上答案 0 :(得分:2)
最简单的选择是使用Rc<RefCell<Structure>>
而不是Box<Structure>
。
Rc<T>
支持类型为T
的值的共享所有权,通过自动生存期管理,您可以拥有多个指向同一对象的指针。 Rc<T>
不是线程安全的;如果以后发现需要线程安全,则可以改为使用Arc
。
RefCell<T>
允许您在运行时而不是在编译时强制执行Rust借用规则(即可以有一个&mut
借用或任意数量的&
借用) :这意味着可以有多个路径,只要您实际上不这样做,就可以通过该路径来变异同一对象。
我在playground上举了一个完整的例子。请注意,这会使用.borrow()
和.borrow_mut()
,如果您实际上违反了借用规则(例如,一次可变地多次借用相同的Structure
),则会感到恐慌。