I want to explicitly destroy an object (call the destructor on it and all its fields), but it may happen that I still hold some pointers to the object in question. Thus, I don't want to yet free the memory; instead I would like to leave a sort of a flag "I am a destroyed object".
I came with an idea of the following approach:
class BaseClass { //all objects in question derive from this class
public:
BaseClass() : destroyed(false) {}
virtual ~BaseClass() {}
private:
bool destroyed;
public:
bool isDestroyed() { return destroyed; }
void destroy() {
this->~BaseClass(); //this will call the virtual destructor of a derivative class
new(this) BaseClass();
destroyed=true;
}
};
When destroy
is called, I basically destroy the whatever object I had (perhaps a derivative one) and create a new "zombie" one in that very same place. As a result I hope to achieve:
ptr
previously pointing to this object can still call ptr->isDestroyed()
to verify its existence.BaseClass
)delete
is still correct?Questions:
Are there any other problems which I should consider when using the above pattern?
Will calling delete
on the zombie object correctly free whole memory consumed by the previous (normal) object?
While I appreciate your input on how to do it differently, and I may be inclined to do it your way - I would still like to understand all the risks that the above code poses.
You got some nasty comments to your question. Now I don't think they are deserved although there may be better ways to do what you want. I understand where you are coming from but actually you are using the destructor the same way you would use the reset function you refuse to write. Actually you gain nothing from calling a destructor since calling a distructor has nothing to do with actually deleting or resetting anything unless you actually write the code to do it within the destructor.
As to your question about the placement new:
As you may know already the placement new doesn't allocate any memory so calling it will just create the object in the same place. I understand that is exactly what you want but it's just not ncessary. Since you don't call delete on your object just destroy, you can set destroyed to true without initializing the class.
To sum it up:
To do what you want to do correctly and gain the benefits of destructors, you should overload the new and delete operators of your classes and use the normal destruction mechanism. You can then opt not to release the memory but mark it as invalid or maybe release most of the memory but leave the pointer pointing to some flags.
EDIT
Following the comments I decided to sum up all the risks I see and the risks that others have pointed out:
And I repeat my suggestion - overload delete and new for what you want
There is a suggestion of using smart pointers. In fact - I am doing that, but my references are circular. I could use some fully-fledged garbage collectors, but since I know myself where (and when!) circle chains can be broken, I want to take advantage of that myself.
Then you can explicitly null-ify (reset if you are using shared_ptr
) one of the circular smart pointers and break the cycle.
Alternatively, if you know where the cycles will be in advance, you should also be able to avoid them in advance using weak_ptr
in place of some of the shared_ptr
s.
--- EDIT ---
If an object referenced by weak pointers only would merely get flagged as "invalid" and release control over all its contained pointers (is this sentence clear?), I would be happy.
Then weak_ptr::expired
should make you happy :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With