Инициализация массива изменяемой ссылки на структуру
Я имею 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]
в нужный массив, но я столкнулся с невозможностью многократного заимствования изменяемых элементов этого массива.
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
вызывает "продвижение" временного в стек - см. Почему законно заимствовать временное? для дополнительной информации. Но это не так, как вы должны решить эту проблему: вам нужно что-то, чтобы владеть Tile
s.
Вы могли бы, например, создать 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
S в отдельных распределениях. Но это не обязательно идеально во всех ситуациях.