Безопасна ли ссылка / ptr на объект, принадлежащий std :: unique_ptr <>, когда unique_ptr находится в векторе? - PullRequest
3 голосов
/ 04 августа 2020

На первый взгляд, мне нравится шаблон наличия контейнера unique_ptr для собственных данных. Мой вопрос: безопасно ли затем использовать указатели / ссылки на члены такого собственного объекта, если я знаю, что unique_ptr не будет go вне области действия?

Например, у меня может быть

auto v = std::vector<std::unique_ptr<ClassWithFooMember>>{};
v.emplace_back(std::make_unique<ClassWithFooMember>());

Могу ли я тогда безопасно сделать

auto *foo_ptr = &(v.at(0)->foo);

, если я знаю, что v переживет foo_ptr и что v никогда не удалит элемент?

Что произойдет, если к v будет добавлено много элементов или если внутреннее представление v изменится? Изменится ли когда-нибудь расположение памяти экземпляров ClassWithFooMember?

Спасибо.

1 Ответ

3 голосов
/ 04 августа 2020

Поскольку объекты ClassWithFooMember «внутри», такие как vector, выделяются отдельно , ваш foo_ptr (или указатель на весь ClassWithFooMember объект) будет остаются действительными независимо от любых операций с v, пока существует (анонимный) объект ClassWithFooMember. Например, сортировка v или его перераспределение безвредны. v.erase(v.begin()), конечно, уничтожит его, но даже тогда вы могли бы сначала написать любое из

auto p=std::move(v.front());
auto *q=v.front().release();

, что позволит объекту жить после полного уничтожения v.

Все это верно вне зависимости от типа контейнера ; это преимущество, оплачиваемое дополнительной памятью и временем накладными расходами , используемыми для отдельного выделения. Также он не указывает на c на std::unique_ptr (хотя в целом это хороший выбор по другим причинам); std::vector<T*> будет иметь такое же поведение, включая то, что было бы безопасно сохранить T* (или указатель на a T), но не T*& (или T**), ссылающийся элементу vector самому . (Соответствующая небезопасная вещь в вашем случае будет содержать std::unique_ptr<ClassWithFooMember>& или std::unique_ptr<ClassWithFooMember>*, чего вам вообще не следует делать в любом случае.)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...