Sign in to follow this  
Crazyfool

Self deleting?

Recommended Posts

I am not sure what to call it but I came across a weird thing (maybe a problem) today. I have an NPC class, and when its update()ed, it checks to see if its dead or not, and if its dead, it cleans up what it needs to do. Though, part of it, tells the place where its stored, to get rid of it. However, this all takes place IN the NPC's method. My question is, if the NPC itself called for its memory to be cleared, can it finish off the function? for instance:
NPC::update()
{
...
spawnpoint->killNpc(id); //memory gets cleared - 
                         //the list storing it uses std::list::erase()
                         //also NULLs the pointers to it

return false; 
}
Things SEEM to work fine, but it seems fishy to me. I wanted to make sure this wasnt undefined behavior or if everything was on the stack thus it didnt matter for that function call whether the NPC object was 'killed' or not.

Share this post


Link to post
Share on other sites
Yes you can self delete by calling
delete this;

You MUST ensure that after calling this, you do not touch any other data variable or call any member function from that class.
More Info

The only problem is that you wont have a way of setting all external pointers pointing to the deleted object to null. If you can ensure that this wont happen, then it should not pose a problem.

Another way to do it is to flag the object dead and have another method from the class containing the object which will delete it and at the same null the pointer.

Share this post


Link to post
Share on other sites
It's no different to calling a member function on a pointer whose object hasn't been allocated yet. If you've never done that, keep it up. Somewhat misleadingly, it can get through quite a lot of code and go a couple of functions deep before it blows up attempting to access a member variable and finding the this pointer is invalid.

Some time I'll have to try to write a class that allocates it's own memory. Just for fun.

Share this post


Link to post
Share on other sites
Quote:
Original post by Crazyfool
I am not sure what to call it but I came across a weird thing (maybe a problem) today.

I have an NPC class, and when its update()ed, it checks to see if its dead or not, and if its dead, it cleans up what it needs to do. Though, part of it, tells the place where its stored, to get rid of it. However, this all takes place IN the NPC's method.


You probably don't really want to do it like this. Doing it this way means the NPC has to "be somewhere", know that it's there, and in fact know just where it is. That actually loses a fair bit of flexibility.

Instead, provide a way for outside code to check if the NPC is dead, and run a pass over the container to remove all the dead ones. Do the cleanup in the destructor of the NPC; that way, you can't forget to invoke it.

It looks something like:


bool isDeadNPC(const NPC&) {
// Return whether the NPC is dead. (May need to be a friend function)
}

Spawnpoint::update() {
// Let all my NPCs update,
std::for_each(npcs.begin(), npcs.end(), std::mem_fun_ref(&NPC::update));
// and then clean up all the ones that got killed.
npcs.erase(std::remove_if(npcs.begin(), npcs.end(), isDeadNPC), npcs.end());
}


Now the NPC doesn't need to know about its container, and it might not need an ID value, either. Although you might need to add a flag for dead-ness. :)

This way also tends to work better if there are complicated NPC-NPC interactions that could lead to either or both dying, and can be faster when deaths are frequent, depending on your container.

Quote:
I wanted to make sure this wasnt undefined behavior or if everything was on the stack thus it didnt matter for that function call whether the NPC object was 'killed' or not.


It will become undefined behaviour if you try to use any of the object's member data, or call any of its virtual member functions, after destruction. Otherwise you should be fine, technically. Note that calling non-virtual member functions is probably a bad idea, though, because you have to make sure they won't use member data, etc. And member functions tend to use member data pretty frequently. (After all, if the function doesn't need access to member data, why make it a member function?)

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this