我有一个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不仅是“具有突变的指针”。这是借来的。这意味着它不能拥有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会导致该临时文件“提升”到堆栈中-有关更多信息,请参见Why is it legal to borrow a temporary?。但这不是解决此问题的方法:您需要一些东西来拥有Tile

例如,您可以创建一个Vec<Tile>并在rows中填充对Vec成员的引用。但这并不能解决您的初始化问题,真正的答案是更容易的:您需要拥有的指针,因此请使用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在单独的分配中。但这并不一定在所有情况下都是理想的。

关于rust - 初始化对struct的可变引用的数组,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/53788733/

10-12 04:41