Sign in to follow this  

C++ Object destruction

This topic is 3661 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

The problem I'm running into is that objects known about their own destruction before anything else, but I can not seem to find a way to delete them internally. Is there a clean way for an object in C++ to delete itself? At the moment I just set the destroyed property to true and then do a loop after updating objects to find those that are destroyed and delete them. Take into account that these objects are in a vector. In your experience have any of you run into this problem, or even better found a good solution?

Share this post


Link to post
Share on other sites

void MyClass::Die()
{
delete this;
}






You've got to be very careful doing this though - if any objects still have a pointer to the object after it deletes itself then you're guaranteed to have some crashes pop up!

[Edit] I just realised you said these objects are in a vector... Is that a vector of objects (vector<MyClass>) or a vector of pointers to objects (vector<MyClass*>)?

If the latter, you could do something like this:

class MyClass;
typedef std::vector<MyClass*> MyClassList;

class MyClass
{
private:
MyClass();//default constructor not usable

MyClassList& m_Owner;
protected:
MyClass( MyClassList& owner ) : m_Owner(owner)
{
m_Owner.push_back( this );//add self to list
}
virtual ~MyClass()
{//remove self from list
MyClassList::iterator i = m_Owner.find(this);
if( i == m_Owner.end() )
std::cout << "Error: already removed from list???" << std::endl;
else
m_Owner.erase( i );
}
public:
MyClass* CreateNew( MyClassList& owner )
{
return new MyClass( owner );
}

void Die() { delete this; }
};

MyClassList myVectorOfObjects;//create your vector
MyClass* pThing = MyClass::CreateNew( myVectorOfObjects );//adds a new MyClass to the vector
pThing->Die();//deletes the object, removes it from the vector
pThing = NULL;



[EDIT #2]
You might want to check out these links:
Is it legal (and moral) for a member function to say delete this?
What is the "Named Constructor Idiom"?

Share this post


Link to post
Share on other sites
[16.15] Is it legal (and moral) for a member function to say delete this?

I would highly advise against writing "delete this", simply because its ugly and there is surely an easier way to accomplish what you want.

However it sounds to me like you really want to be using boost::ptr_vector<T>, but we won't be sure until you tell us why you are doing what you're doing.

Share this post


Link to post
Share on other sites
Quote:
Original post by yahastu
Yeah..there is really no circumstance where an object should ever delete itself.


Intrusive reference counting. Ever try implementing a COM interface?

Share this post


Link to post
Share on other sites
Quote:
Original post by WarisSweet
set the destroyed property to true and then do a loop after updating objects... in a [container].


Instead, have the update function return a bool indicating living/dead status, and use it as a predicate with the erase/remove idiom:


bool Thing::update() {
// return true for dead objects
}

std::erase(std::remove_if(things.begin(), things.end(), std::mem_fun_ref(&thing::update)), things.end());

Share this post


Link to post
Share on other sites
Quote:
Original post by Zahlman

std::erase(std::remove_if(things.begin(), things.end(), std::mem_fun_ref(&thing::update)), things.end());


I believe it's relevant to mention that the reason this will work without weird problems is because remove_if guarantees that the predicate is called exactly once per object [smile]

Share this post


Link to post
Share on other sites
Quote:
Original post by ToohrVyk
Quote:
Original post by Zahlman

std::erase(std::remove_if(things.begin(), things.end(), std::mem_fun_ref(&thing::update)), things.end());


I believe it's relevant to mention that the reason this will work without weird problems is because remove_if guarantees that the predicate is called exactly once per object [smile]


I was thinking about this earlier, and was about to ask. I take it this is a safe (and legal) method of updating tasks which are stored in a std::container, and may need to remove themselves?

Share this post


Link to post
Share on other sites
Quote:
Original post by swiftcoder
Quote:
Original post by ToohrVyk
Quote:
Original post by Zahlman

std::erase(std::remove_if(things.begin(), things.end(), std::mem_fun_ref(&thing::update)), things.end());


I believe it's relevant to mention that the reason this will work without weird problems is because remove_if guarantees that the predicate is called exactly once per object [smile]


I was thinking about this earlier, and was about to ask. I take it this is a safe (and legal) method of updating tasks which are stored in a std::container, and may need to remove themselves?


If the logic behind "may need to remove themselves" is sufficiently simple, yes*. If updating an object could influence some other object's decision on the matter, you may have problems. Especially if that other object appears earlier in the container.

* for standard library *sequences*. I wouldn't try it on a std::map if I were you.

Share this post


Link to post
Share on other sites
Quote:
Original post by SiCrane
Quote:
Original post by yahastu
Yeah..there is really no circumstance where an object should ever delete itself.


Intrusive reference counting. Ever try implementing a COM interface?


No I haven't implemented a COM interface, but I have done similar interfaces with reference counting for my own projects...and I would argue that intrusive reference counting is a bad paradigm, it would be better if the user pointer was not to the actual object itself..but to a container that holds the pointer, so that "obj->Release()" does not make the "obj" pointer invalid.

Share this post


Link to post
Share on other sites
Quote:
Original post by yahastu
No I haven't implemented a COM interface, but I have done similar interfaces with reference counting for my own projects...and I would argue that intrusive reference counting is a bad paradigm, it would be better if the user pointer was not to the actual object itself..but to a container that holds the pointer, so that "obj->Release()" does not make the "obj" pointer invalid.


A project I'm working on ATM uses a home-made ref-counting system, where the objects hold the ref-count as a member variable and call 'delete this' when the ref-count hits zero.

I don't really see the problem though, as there is no explicit way to call 'Release()' on the object - the only way to release it is to set all of the smart pointers to zero or another object (at which point the object's ref-count becomes 0). So you're guaranteed that when the object is deleted there are no pointers still pointing to it (unless someone has done something stupid and used a raw-pointer in place of a smart-pointer).


The game-engine we're using also uses a similar system, where there is a base class called RefObject which provides a "virtual void DeleteThis()" function that's called when the ref-count hits zero.

Share this post


Link to post
Share on other sites

This topic is 3661 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

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