Инициализация массива изменяемой ссылки на структуру - PullRequest
0 голосов
/ 15 декабря 2018

У меня есть 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 Ответ

0 голосов
/ 15 декабря 2018

&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 hasnне реализует 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 в отдельных выделениях.Но это не обязательно идеально во всех ситуациях.

...