“删除这个”有什么用?

问题描述 投票:0回答:4

今天,我看到了一些遗留代码。在析构函数中有一个类似“

delete this
”的语句。我认为,这个调用将是递归的。为什么它有效?

我在Y!上快速搜索了一下,发现如果需要限制用户创建堆栈对象,我们可以将析构函数设为私有,并提供删除实例的接口。在提供的接口中,我们必须对该指针调用delete。

还有其他使用此类语句的情况吗?

c++ memory-management destructor self-destruction
4个回答
33
投票

“delete this”通常用于引用计数对象。对于引用计数对象,何时删除的决定通常由对象本身决定。下面是 Release 方法的示例 [1]。

int MyRefCountedObject::Release() {
  _refCount--;
  if ( 0 == _refCount ) {
    delete this;
    return 0;
  }
  return _refCount;
}

ATL COM 对象是这种模式的一个主要示例。

[1] 是的,我意识到这不是线程安全的。


24
投票

delete this
在 C++11 中有效

在析构函数中调用

delete this
是有效的。 C++ FAQ 有一个关于此的条目。 C++11 [basic.life] p5 的限制不适用于正在销毁的对象,并且 [C++11 [class.cdtor] 不限制您使用
delete this

尽管有效,但这很少是一个好主意。

wxWidgets
框架将其用于其线程类。它有一种模式,当线程结束执行时,它自动释放系统资源和自身(wxThread对象)。我觉得这很烦人,因为从外部,你无法知道引用它是否有效 - 你不能再调用像
IsValid
这样的函数,因为该对象不存在。除了不能用于非动态对象的问题之外,这听起来像是
delete this
的主要问题。

如果您这样做,请确保您不再触摸任何数据成员,或在您以这种方式删除的对象上调用任何成员函数。最好将其作为非虚拟、受保护或私有函数中的最后一条语句。调用删除在虚拟和/或公共函数中也是有效的,但我会限制执行此操作的方法的可见性。

delete this
曾经是 C++03 中未定义的行为

delete this
在析构函数中无效。

我上述主张的 C++ 标准引用(C++03 [basic.life] p5):

在对象的生命周期开始之前,但在该对象将占用的存储空间已分配之后,或者在对象的生命周期结束之后,在重用或释放该对象所占用的存储空间之前,任何引用该对象的指针可以使用对象将要或曾经位于的存储位置,但只能以有限的方式使用。 [...] 如果对象将是或曾经是具有非平凡析构函数的类类型,并且指针用作删除表达式的操作数,则程序具有未定义的行为。

当对象的析构函数开始执行时,生命周期结束。请注意,对于正在构造和销毁的对象,该段落之后的规则有一些例外(例如,您可以访问 POD 类型的非静态数据成员),详细信息请参阅C++03 [class.cdtor]


3
投票

在早期的 C++ 时代,这样做有充分的理由。例如,引用计数对象的自删除(如 JaredPar 所说)。 据我所知,从长远来看,它们都被认为是一个坏主意。


2
投票

在双向链表中,可以在不引用任何外部结构(例如高级“列表”对象)的情况下删除节点。这使得每个节点可以合理地处理自己的释放(可能与互补的静态方法相结合来处理来自同一内存池的初始分配)。在这种情况下,节点对象删除自身可能是有意义的(当用户请求时)。

void RemoveAndDeallocate()
{
    LinkedListNode *current_prev = prev, *current_next = next;
    current_prev->next = current_next;
    current_next->prev = current_prev;
    delete this;
}

尽管如此,节点从一个列表中取消链接并链接到另一个列表中而不释放任何内存也是合理的,因此单个删除操作无条件释放内存是不可取的。

© www.soinside.com 2019 - 2024. All rights reserved.