我有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]
转换为所需数组的函数,但是我无法多次借用该数组的可变元素。
答案 0 :(得分:1)
&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
s。
例如,您可以创建一个Vec<Tile>
,并用对rows
成员的引用来填充Vec
。但这并不能解决您的初始化问题,真正的答案更容易:您想要拥有 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
存储在单独的分配中。但这并不一定在所有情况下都是理想的。