C++ “有什么用?”;删除此“;?
今天,我看到了一些遗留代码。在析构函数中有一个类似“C++ “有什么用?”;删除此“;?,c++,memory-management,destructor,self-destruction,C++,Memory Management,Destructor,Self Destruction,今天,我看到了一些遗留代码。在析构函数中有一个类似“删除此””的语句。我想,这个调用将是递归的。它为什么起作用 我在Y上快速搜索了一下!,我发现,如果需要限制用户创建堆栈对象,我们可以将析构函数设置为私有,并提供一个删除实例的接口。在提供的接口中,我们必须对该指针调用delete 使用此类语句还有其他情况吗?“删除此项”通常用于ref计数的对象。对于ref计数对象,何时删除的决定通常放在对象本身上。下面是一个发布方法的示例[1] int MyRefCountedObject::Release()
删除此”
”的语句。我想,这个调用将是递归的。它为什么起作用
我在Y上快速搜索了一下!,我发现,如果需要限制用户创建堆栈对象,我们可以将析构函数设置为私有,并提供一个删除实例的接口。在提供的接口中,我们必须对该指针调用delete
使用此类语句还有其他情况吗?“删除此项”通常用于ref计数的对象。对于ref计数对象,何时删除的决定通常放在对象本身上。下面是一个发布方法的示例[1]
int MyRefCountedObject::Release() {
_refCount--;
if ( 0 == _refCount ) {
delete this;
return 0;
}
return _refCount;
}
ATL COM对象就是这种模式的主要示例
[1] 是的,我知道这不是线程安全的。删除此在析构函数中无效。它可以在其他地方使用。但这很少是个好主意。
wxWidgets
框架将其用于线程类。它有一种模式,当线程结束执行时,它会自动释放系统资源和自身(wxThread对象)。我觉得它很烦人,因为从外部看,你不知道引用它是否有效——你不能再调用像IsValid
这样的函数了,因为对象不存在。这听起来像是删除此
的主要问题,除了它不能用于非动态对象之外
如果这样做,请确保不要触摸任何数据成员,也不要再对以这种方式删除的对象调用任何成员函数。最好将其作为非虚拟、受保护或私有函数中的最后一条语句。调用delete在虚拟和/或公共函数中也是有效的,但我会限制执行该操作的方法的可见性
政府对此有一条记录。C++标准引用我的上述要求(<代码> 3.8p5< /代码>):
在对象的生存期开始之前,但在分配对象将占用的存储之后,或者在对象的生存期结束之后,在重用或释放对象占用的存储之前,任何指向对象将要或曾经所在的存储位置的指针都可以使用,但只能以有限的方式使用。[…]如果对象将是或曾经是具有非平凡析构函数的类类型,并且指针用作删除表达式的操作数,则程序具有未定义的行为
生命周期在对象的析构函数开始执行时结束。请注意,对于正在构建和销毁的对象(例如,允许访问非静态数据成员),在段落之后出现的规则有例外,详见<代码> 12.7代码> > < /p> 。在C++的早期,认为这是很好的理由。例如,引用计数对象的自删除(正如JaredPar所说)。
据我所知,从长远来看,它们都是一个坏主意。在双链接列表中,可以删除节点而不引用任何外部结构,例如高级“列表”对象。这使得每个节点处理自己的释放(可能与一个互补的静态方法结合处理来自同一内存池的初始分配)是合理的。在这种情况下,节点对象删除自身(当用户请求时)是有意义的
尽管如此,在不释放任何内存的情况下,将节点从一个列表中取消链接并链接到另一个列表也是合理的,因此不希望单个删除操作无条件释放内存。而自删除参照计数对象是一种非常常见的模式,我认为最初的问题是把它放在析构函数中,而不是放在Release()函数中,在这种情况下,它简直是疯了。@rmeador,实际上有两个问题。标题和最后一句都表明,我们想知道“删除此项;”的有效用法。我希望我能回答这个问题。中间部分确实提出了一个问题:“为什么要在dtor中删除此项?”。我同意这样做似乎有点疯狂。您的示例代码有一个bug。如果_refCount是一个成员变量,那么当您“删除此”时,该成员变量将不再存在,因此您的“return _refCount”行具有未定义的行为。这正是我的想法。今天,如果我需要编写一个ref counted对象,我会将数据保存在一个额外的对象中,并在reference count降至零时使宿主对象(复制的对象)删除包装的数据。自我删除气味:)@johannesschaub-litb:完全同意;负责其职责并决定何时清理自身的对象?恶心@Johanneschaub litb然后主机对象必须在完成时自行删除。。。
void RemoveAndDeallocate()
{
LinkedListNode *current_prev = prev, *current_next = next;
current_prev->next = current_next;
current_next->prev = current_prev;
delete this;
}