I’m writing a relatively big project in C++ and have a problem with object deletion. The project, to be precise is a roguelike game.
I have a class Npc which is every monster in the game. They are created and stored in a separate class, Storage<Npc>, that is responsible for their management (loading, saving, creation, deletion, etc). Whenever a monster dies, corresponding object npc has to be deleted and destroyed completely. It is not a problem to delete object itself, I just have invoke a method from Storage<NPC>. The problem is that code contains a lot of pointers to this already-dead npc, which are now invalid and trying to use them will cause a lot of issues. For example:
- There may be an action he intended to perform before he died.
- Tile on which he stood record store a pointer to him.
- He may have been involved in some continuous activities, like grappling somebody.
There are a lot of such pointers in the code, so it is nearly impossible to simply track them. What I need is some way to determine that an npc is already dead, and there is no actual object stored on that address, so that parts of code which still have this pointer can adequately react to his death.
I myself have come up with several ideas, but so far none of them seems really good to me:
- I could ask
Storage<NPC>class if it has an object on such address. The potential problem is that after object deletion, another object may be allocated on the same address, which will cause bugs. - I could notify all locations that could possibly use the invalid pointer. It is a bad idea because number of such locations will increase over time and doing this is a pain.
- I could implement some version of smart pointer, but I’m unsure on which one to use.
tl;dr version: I need a solution that will tell me if a pointer points to an object, or it points to a free chunk of memory, or to some other object, allocated after original object deletion.
How about using weak pointers? If you store the
Npcin astd::shared_ptr(C++11, usestd::tr1::shared_ptrfor C++03), you can then createstd::weak_ptrs (C++11 again, usestd::tr1::weak_ptrfor C++03) that refer to theshared_ptr. When theshared_ptractually deletes its object, then all theweak_ptrs will be able to figure this out.Although I have to wonder why you’re deleting
Npcs that are still being used elsewhere (e.g. that still have actions). If instead of trying to have all these other references discover you’ve deleted theNpc, you just want theNpcto die once all references disappear, then using ashared_ptrby itself (with noweak_ptr) will work correctly.