首页 > 解决方案 > 一个数组如何包含对同一对象的多个可变引用?

问题描述

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

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

我试过这个&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

现在这只是单线程,所以没有什么需要是线程安全的

我把代码放在操场上

标签: rust

解决方案


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

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

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

我在操场上放了一个完整的例子。请注意,这使用.borrow()and .borrow_mut(),如果您实际上最终违反了借用规则(例如,通过一次可变地多次借用相同的内容Structure),它将感到恐慌。


推荐阅读