初始化结构的可变引用数组

Initialising an array of mutable reference to struct

我有 struct Board 其中包含一个元素 rows: [[&'a mut Tile; 7];7]

由于生命周期的原因,我不知道如何通过 impl Board {} 块中的构造函数对其进行初始化,因此我尝试在 main 函数中对其进行初始化。

遗憾的是,rows = [[&mut Tile::def(); 7]; 7] 不起作用,因为 Rust 想要复制引用 &mut Tile::def()。 (其中 Tile::def()Tile 的构造函数)。

有没有办法初始化这个数组,使每个元素 (i,j) 都是对不同 Tile 的引用?

目前,唯一可行的解​​决方案是

let mut rows = [[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()]];

let board = Board { rows : rows, ...};

由于显而易见的原因,这并不令人满意。

我曾尝试创建一个将 [[Tile; 7]; 7] 转换为所需数组的函数,但我遇到了无法多次借用该数组的可变元素的问题。

&mut 不仅仅是 "a pointer with mutation"。这是。这意味着它不能 拥有 Tile,它必须属于其他地方。

这种方法

let mut rows = [[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()],[&mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def(), &mut Tile::def()]];

之所以有效,是因为每个人 Tile::def() 创建了一个新的临时 Tile,而 &mut 导致临时 "promoted" 进入堆栈 - 请参阅 了解更多信息。但这不是解决此问题的方法:您需要一些东西来 拥有 Tiles.

例如,您可以创建一个 Vec<Tile> 并使用对 Vec 成员的引用填充 rows。但这并没有解决你的初始化问题,真正的答案更简单:你想要一个 owning 指针,所以使用 Box<Tile> 而不是 &mut Tile.

Box 没有实现 Copy,但它确实实现了另一个使这项工作更容易的特性:Default.

impl Default for Tile {
    fn default() -> Self {
        Tile::def()
    }
}

fn main() {
    let mut rows: [[Box<Tile>; 7]; 7] = Default::default();
}

根据 Tile::def 的功能,您也可以 #[derive(Default)] 而不是手动实施。


我鼓励您考虑另一种选择:将所有 Tile 存储在 Vec 中,但通过索引而不是任何类型的指针来引用它们。交换两个索引很便宜,如果需要,可以很容易地增加 Vec,它可以将 rows 与其后备存储一起存储而不会出现生命周期问题,并且它对缓存更友好(这可能意味着更好的性能)比将所有 Tile 存储在单独的分配中。但它不一定在所有情况下都是理想的。