今天,我看到了一些遗留代码。在析构函数中有一个类似“delete this
”的语句。我想,这个调用将是递归的。它为什么有效?
我在Y!上做了一些快速搜索,我发现如果需要限制用户创建堆栈对象,我们可以将析构函数设为私有,并提供删除实例的接口。在提供的接口中,我们必须在此指针上调用delete。
使用此类陈述是否还有其他情况?
答案 0 :(得分:32)
“删除此”通常用于引用计数对象。对于ref计数对象,何时删除的决定通常放在对象本身上。以下是Release方法的示例[1]。
int MyRefCountedObject::Release() {
_refCount--;
if ( 0 == _refCount ) {
delete this;
return 0;
}
return _refCount;
}
ATL COM对象是此模式的主要示例。
[1]是的,我发现这不是线程安全的。
答案 1 :(得分:24)
delete this
在析构函数中无效。它可以在别处使用。但这只是一个好主意。 wxWidgets
框架将它用于其线程类。它有一种模式,当线程结束执行时,它会自动释放系统资源和自身(wxThread对象)。我发现它非常烦人,因为从外面看,你不知道引用它是否有效 - 你不能再调用IsValid
之类的函数,因为该对象不存在。这有点像delete this
的主要问题,除了它不能用于非动态对象的问题。
如果您这样做,请确保不要触摸任何数据成员,或者在您删除的对象上再调用任何成员函数。最好将它作为非虚拟,受保护或私有函数中的最后一个语句。调用delete也在虚拟和/或公共函数中有效,但我会限制方法的可见性。
C++ FAQ有关于此的条目。关于我上述索赔的标准报价(3.8p5
):
在对象的生命周期开始之前但在对象占用的存储空间已经被分配之后,或者在对象的生命周期结束之后以及在重用或释放对象占用的存储之前,任何引用的指针可以使用对象将位于或位于的存储位置,但仅限于有限的方式。 [...] 如果对象是或者是具有非平凡析构函数的类类型,并且指针用作delete-expression的操作数,则程序具有未定义的行为。
生命周期在对象的析构函数开始执行时结束。请注意,对于正在构建和销毁的对象(例如,您可以访问非静态数据成员),该段落之后的规则有例外情况,详见12.7
。
答案 2 :(得分:3)
在C ++早期的日子里,这被认为是很好的理由。例如,自我删除引用计数对象(如JaredPar所说)。 据我所知,从长远来看,他们都被认为是一个坏主意。
答案 3 :(得分:2)