Can I delete an object owned by another with a callback from the object to be deleted?
I have one class (A
) which knows when it should be deleted. I believe an object cannot directly delete itself (i.e., you can't call a destructor from inside it) so I've used a callback.
Here is the pseudo-code of my current solution:
class A {
Owner* owner; // is set in constructor
A(Owner* ow) : owner(ow) {}
void willDeleteOurself() {
owner->deleteObject();
}
}
class Owner {
A* obj;
Owner() { // e.g. constructor
obj = new A(this);
}
void deleteObject() {
delete obj;
}
}
I have an object of class Owner
which owns an object of class A
. Now, at some point, obj
"knows" that it should be deleted, and a call of willDeleteOurself()
occurs. This code seems to work.
Now, my question is this: Is this a safe way to delete obj
?
I'm concerned because when the method deleteObject
returns (reaches }
), it jumps back to the end of willDeleteOurself()
, but the object from whence that method was called has been destroyed.
Is this construct safe when I have no more statements referencing obj
after the call to owner->deleteObject();
?
Update:
Thanks for the answers. I simplified a bit here. I do not have A* obj;
, but a boost smartpointer (alone and sometimes in a map) to the object. I think if I call delete this
on the wrapped object, the smartpointer will not recognize that the underlying object is deleted. Is that correct?
A开发者_高级运维s delete this
(and also my code above) is "dangerous", is there a safer way to solve my problem?
This is actually just as good as calling delete this;
in willDeleteYourself
. It is fine if you do not access any members after the delete.
An object cannot directly delete itself
There is no particular reason why an object cannot delete
itself, you have to be careful not to access any member after the object has been deleted, but there are circumstances where it makes sense.
I have done that with some fire-and-forget objects encapsulating a thread or timer. They were not really owned by any other object, so they might be created dynamically and leaked until they complete their work. Then they would call delete this;
as the very last operation.
Adding intermediate steps from the point where you need (or want) to delete the object and the delete code itself will only make things more complex and harder to maintain. The following code:
void willDeleteOurself() {
delete this;
// [1]
}
is much more explicit and easy to read: from this point on, the object is dead, you cannot use it, do not add code in [1], because the object is dead now. If on the other hand, you disguise the delete
through the callback, then others might see the code and not realize that adding code to [1] is dangerous.
精彩评论