может ли std :: list содержать разные std :: unique_ptr ‹T›?

Итак, я создаю класс игрового менеджера для Qub3d Engine и хочу, чтобы каждый GameState был std::unique_ptr

Каждый GameState, такой как mainMenu, который у меня есть, является дочерним классом GameState

Мне нужно, чтобы std::list(or something) содержал разные unique_ptr для каждого состояния, например mainMenu и mainGame.

Я пробовал std::list< std::unique_ptr<GameState> > stateStack;, но когда я пытаюсь сделать это: stateStack.push_back(m_mainMenu); Я получаю сообщение об ошибке C2664 о перегрузке, не включая класс mainMenu. (Не знаю, актуально ли это, но я использую MSVC)

Как бы я этого добился? И возможно ли это вообще?


person TMcSquared    schedule 05.03.2018    source источник
comment
std::unique_ptr к базовому классу также может обрабатывать производный класс. Так что сделайте std::list из std::unique_ptr базовым классом.   -  person Dannyu NDos    schedule 05.03.2018
comment
Вы имеете в виду что-то вроде этого std::list<std::unique_ptr<GameState>> states;?   -  person Galik    schedule 05.03.2018
comment
Вам действительно нужен std :: list? std :: vector не подойдет?   -  person DeiDei    schedule 05.03.2018
comment
@DannyuNDos и @Galik Я пробовал это, но получаю сообщение об отсутствии перегрузки, когда я пытаюсь вернуть mainMenu класс. @DeiDei на данный момент мне все равно, потому что он должен работать независимо от того, какой из них я использую, хотя я, вероятно, буду использовать вектор.   -  person TMcSquared    schedule 05.03.2018
comment
@TMcSquared Какой тип m_mainMenu? Это должно быть std::unique_ptr<GameState> или std::unique_ptr<mainMenu>.   -  person Dannyu NDos    schedule 05.03.2018
comment
@DannyyuNDos тип m_mainMenu - mainMenu   -  person TMcSquared    schedule 05.03.2018
comment
@TMcSquared Вы не можете поместить скалярный объект в список интеллектуальных указателей.   -  person Dannyu NDos    schedule 05.03.2018
comment
извините, это умный указатель типа mainMenu   -  person TMcSquared    schedule 05.03.2018


Ответы (1)


Это абсолютно возможно, но для этого вам нужно изменить то, как вы думаете об указателях.

unique_ptr означает гарантию того, что на объект будет только один указатель. Он управляет временем жизни объекта, на который указывает, и, таким образом, помогает предотвратить возможные ошибки памяти и ошибки.

Таким образом, unique_ptr должен быть определен в контексте, в котором он живет. Вы не можете просто передать случайный указатель на структуру данных и заставить ее стать unique_ptr.

В терминах std::vector вы можете использовать функцию emplace_back() в сочетании с оператором new. Эта функция фактически обрабатывает инициализацию рассматриваемого объекта, в отличие от push_back(), который только добавляет существующий объект в структуру данных.

std::vector<std::unique_ptr<Dog>> dogshow;
dogshow.emplace_back(new Dog());
dogshow[0]->speak();  // outputs "woof", consistent with my Dog class.

Проще говоря, функция emplace_back берет на себя объявление unique_ptr.

Если вы абсолютно хотите использовать вместо этого std::list, это предлагает аналогичную функцию emplace. Многие стандартные структуры данных C ++ делают.


ПРИМЕЧАНИЕ. Если вы хотите интеллектуальное управление памятью для unique_ptr, но хотите иметь несколько указателей на один и тот же объект, вам следует взглянуть на shared_ptr.

person CodeMouse92    schedule 06.03.2018