У меня есть коллекция объектов Creature, которые создаются и принадлежат одной части моего приложения, используя std::make_shared и std::shared_ptr.
Я также отслеживаю выбор нуля или одного Creature в объекте World, используя std::weak_ptr<Creature>.
void World::SetSelection(const std::shared_ptr<Creature>& creature) {
selection = creature;
}
std::shared_ptr<Creature> World::GetSelection() const {
return selection.lock();
}
Вызывающий GetSelection отвечает за проверку пустого указателя. Если это так, значит, в настоящее время нет выбора.
Все это отлично работает по моему вкусу: когда выбранный Creature умирает от естественных причин (в другом месте приложения), GetSelection снова возвращает nullptr, как будто ничего не было выбрано.
Однако в этом случае член World::selection все еще указывает на блок управления std::shared_ptr. Это может быть довольно большим, потому что я использую std::make_shared для создания объектов Creature (я понимаю, что объект Creature был правильно уничтожен в нужное время, но память для него все еще выделена). Я рассматриваю возможность изменения GetSelection на следующее:
std::shared_ptr<Creature> World::GetSelection() {
const auto ret = selection.lock();
if (!ret)
selection.reset();
return ret;
}
Это освобождает память, как только я замечаю, что это больше не нужно. Раздражающе, эта версия GetSelection не может быть const.
Мои вопросы:
-
Какую версию
GetSelectionможно считать лучшей практикой в этой ситуации? -
Изменяется ли ответ, если что-то подобное происходит в шаблоном коде, где
sizeof(T)неизвестно и может быть огромным? Или в С++ 14, гдеstd::make_shared<T[]>может быть задействован? -
Если вторая версия всегда лучшая, в чем смысл
std::weak_ptr<T>::expiredиlockне делать это сами?