Я пишу относительно большой проект на C ++ и имею проблему с удалением объекта. Проект, если быть точным, это игра в стиле roguelike.
У меня есть класс Npc
который каждый монстр в игре. Они создаются и хранятся в отдельном классе, Storage<Npc>
, который отвечает за их управление (загрузка, сохранение, создание, удаление и т. д.). Всякий раз, когда умирает монстр, соответствующий объект npc
должен быть удален и уничтожен полностью. Удалить сам объект не проблема, я просто вызвал метод из Storage<NPC>
, Проблема в том, что код содержит много указателей на этот уже мертвый npc
, которые сейчас недействительны и попытка их использования вызовет много проблем. Например:
В коде много таких указателей, поэтому практически невозможно просто отследить их. Мне нужен какой-то способ определить, что npc
уже мертв, и по этому адресу не хранится фактический объект, так что части кода, которые все еще имеют этот указатель, могут адекватно реагировать на его смерть.
Я сам выдвинул несколько идей, но пока ни одна из них не кажется мне действительно хорошей:
Storage<NPC>
класс, если у него есть объект по такому адресу. Потенциальная проблема заключается в том, что после удаления объекта другой объект может быть размещен по тому же адресу, что приведет к ошибкам.TL; Dr версияМне нужно решение, которое скажет мне, если указатель указывает на объект, или он указывает на свободный кусок памяти, или на некоторый другой объект, выделенный после удаления исходного объекта.
Как насчет использования слабых указателей? Если вы храните Npc
в std::shared_ptr
(C ++ 11, используйте std::tr1::shared_ptr
для C ++ 03), вы можете создать std::weak_ptr
s (снова C ++ 11, используйте std::tr1::weak_ptr
для C ++ 03), которые относятся к shared_ptr
, Когда shared_ptr
на самом деле удаляет свой объект, то все weak_ptr
S сможет понять это.
Хотя мне интересно, почему вы удаляете Npc
s, которые все еще используются в другом месте (например, которые все еще имеют действия). Если вместо того, чтобы пытаться обнаружить все эти ссылки, вы удалили Npc
ты просто хочешь Npc
умереть, как только все ссылки исчезнут, а затем с помощью shared_ptr
сам по себе (без weak_ptr
) будет работать правильно.
С предоставленной вами информацией я могу предложить вам Шаблон наблюдателя.
Если есть код, который должен реагировать на смерть неигрового персонажа, этот путь — путь. Разделы кода, имеющие ссылки на указатель на вашего NPC, будут уведомлены о смерти NPC и обнулит свою копию указателя на NPC, и при необходимости отреагируют на смерть NPC. Уведомление о смерти отправлено всем observers
до того, как NPC фактически удален.
С помощью этого паттерна вы можете реализовать такую механику, как «Герой получает 50 HP за каждого убитого монстра», и она легко масштабируется.
Вы также можете использовать предложение Кевина Балларда об использовании shared_ptr
если никакой код не должен активно реагировать на смерть NPC, а просто должен обработать случай, когда NPC мертв.
Одним из вариантов является включение подсчета ссылок в ваш класс. Когда какой-либо другой объект (например, комната) будет содержать указатель на NPC, комната несет ответственность за увеличение количества ссылок NPC. Теперь, вместо того, чтобы просто удалить мертвый NPC, вы помечаете его как мертвый (через другой новый элемент данных, если у вас еще нет правильного флага), и удаляете только, если его счетчик ссылок равен нулю. Комнатный объект также обязан периодически проверять этот флаг, и если он узнает, что npc мертв, он уменьшает его счетчик ссылок (что приведет к удалению после вскрытия, если счет теперь равен нулю).