У меня есть коллекция объектов 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
не делать это сами?