我有一个类(A
),它知道什么时候应该删除它。我相信一个对象不能直接删除它自己(也就是说,你不能从里面调用析构函数),所以我使用了回调。
这是我当前解决方案的伪代码:
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;
}
}
我有一个Owner
类的对象,它拥有A
类的对象。现在,在某个时刻,obj
"知道"它应该被删除,并且发生了对willDeleteOurself()
的调用。此代码似乎有效。
现在,我的问题是:这是删除obj
的安全方法吗
我之所以担心,是因为当方法deleteObject
返回(到达}
)时,它会跳回willDeleteOurself()
的末尾,但调用该方法的对象已被销毁。
当我在调用owner->deleteObject();
之后没有更多引用obj
的语句时,这个构造安全吗?
更新:
谢谢你的回答。我在这里简化了一点。我没有A* obj;
,但有一个指向对象的boost智能指针(单独使用,有时在映射中使用)。我认为,如果我在包装的对象上调用delete this
,智能指针将无法识别底层对象已被删除。这是正确的吗?
由于delete this
(以及我上面的代码)是"危险的",有没有更安全的方法来解决我的问题?
这实际上和在willDeleteYourself
中调用delete this;
一样好。如果您在删除后没有访问任何成员,那也没关系。
对象不能直接删除自身
对象不能delete
本身并没有什么特别的原因,您必须小心,在对象被删除后不要访问任何成员,但在某些情况下这是有意义的。
我已经用一些即发即弃对象封装了一个线程或定时器。它们并不是任何其他对象真正拥有的,因此它们可能是动态创建的,会泄漏直到它们完成工作。然后他们将调用delete this;
作为最后一个操作。
从需要(或想要)删除对象和删除代码本身开始添加中间步骤只会使事情变得更加复杂和难以维护。以下代码:
void willDeleteOurself() {
delete this;
// [1]
}
更明确,更容易阅读:从这一点开始,对象已经死了,你不能使用它,不要在[1]中添加代码,因为对象现在已经死了。另一方面,如果您通过回调来伪装delete
,那么其他人可能会看到代码,而没有意识到向[1]添加代码是危险的。