Инициализация массива изменяемой ссылки на структуру

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

Вы могли бы, например, создать 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 Наряду с хранилищем резервных копий без проблем с продолжительностью жизни, он более кэш-памяти (что может означать лучшую производительность), чем хранение всех TileS в отдельных распределениях. Но это не обязательно идеально во всех ситуациях.

Другие вопросы по тегам