C++ 在虚拟成员函数中“删除此”是否安全?
我已经知道某些形式的“自杀”是安全的(被认为是合法的),但是,在虚拟成员函数中执行C++ 在虚拟成员函数中“删除此”是否安全?,c++,memory-management,C++,Memory Management,我已经知道某些形式的“自杀”是安全的(被认为是合法的),但是,在虚拟成员函数中执行删除此是否特别安全 注意,“安全”是指编译器生成的“代码”是否能够处理构造 注意,我对做这件事的利弊不感兴趣,只是我是否能考虑安全。 附带问题:语言标准是否明确或隐含要求实现支持任何形式的删除此习惯用法 我不认为这是复制品。我的问题是,在虚拟成员函数中这样做是否安全 下面是我追求的目标的概要 class FooBase { protected: virtual void on_idle() { /* no-
删除此
是否特别安全
注意,“安全”是指编译器生成的“代码”是否能够处理构造
注意,我对做这件事的利弊不感兴趣,只是我是否能考虑安全。
附带问题:语言标准是否明确或隐含要求实现支持任何形式的删除此习惯用法
我不认为这是复制品。我的问题是,在虚拟成员函数中这样做是否安全
下面是我追求的目标的概要
class FooBase {
protected:
virtual void on_idle() { /* no-op by default */ }
};
class Foo : public FooBase {
void on_idle() override final
{
delete this;
}
};
注意,虽然需要分配堆,但其他子类可能不需要分配。是,只要以后不使用this
并且任何指向*此
、且此
的其他任何人都不能保证通过new
分配,因为您将其删除为的类型,或者拥有一个虚拟的析构函数。(即,绝不作为另一个对象的成员,在std::vector
中,作为自动存储变量,作为静态变量,作为临时变量,而不是new[]
,而不是放置new
,等等)
这包括调用非虚拟方法、虚拟方法、成员访问、调用DTR以及其他无数事情;除了返回之外,几乎任何东西都可以下一行的code>以及指向*此
的每一个指针在删除此之前被清除代码>(或绝对不使用)
作为一般规则,您必须对对象生命周期进行的控制级别非常高,才能使删除此项
safe,您可以将生存期管理重构为类外部的智能资源所有者,智能资源所有者可能会将其状态保持为pImpl
,并将其删除。喜欢值类型,并且类型删除此项代码>永远不能被视为值
标准中没有要求删除此项代码>对于虚拟
对象来说是非常危险的,而不是更高的继承倾向
所有删除此项的类型
应该有一个虚拟析构函数,或者是final
,以避免继承问题。当我们不知道在哪个上下文中执行时,如何告诉您是否安全?一般来说,删除此
是一个坏主意(事实上,可以确定的例外情况可能存在),但如果有疑问,听起来像是一个糟糕(且不安全)的设计决策。也许,如果你解释一下你为什么要这么做,你可以给出一个更明确的答案。(但你也不可避免地听到了做这件事的缺点,老实说,我认为这是理所当然的,因为软件设计通常发生在一种语言的语义内,C++从来就不意味着<代码>删除这个<代码> >。我不这么认为,我会关注<代码> VTAB< <代码>的后面。但我对答案很感兴趣,所以我会留下这篇评论,因为COM对象使用虚拟方法实现接口,delete this
几乎总是用重写的IUnknown::Release()
方法编写的,然后我不得不说是的,它是安全的。大量的Microsoft/Windows技术都依赖于它。有很多问题,但vtable不在其中。你应该在发布问题之前进行搜索。这里有一个通常的问题,一个函数是否是虚拟的,这不仅关系到它何时被调用,也关系到它何时返回。请确保这是由new创建的,而不是new[]
,但这些是必要的标准预防措施,以便删除此函数代码>即使对于非虚拟对象也是安全的。安全吗?也许,在非常可控的情况下。良好做法?可能不会。你会遇到问题吗?除非代码非常简单,否则是的。请记住,在OO设计中,子类实现自己对虚拟方法的重写,并让其重写方法“调用”超类方法,然后在超类方法返回后执行其他操作是很常见的。如果在超类方法调用期间,他们的this对象从下面被删除,大多数子类方法的作者都会感到非常惊讶,因此他们可能会做一些导致未定义行为或随后崩溃的事情。因此,即使最初正确地实现,“删除这个”也是一个等待发生的错误。@Jeremy-如果继承的函数要执行删除这个
,那么应该仔细记录这一事实。派生版本只能在调用继承版本之前执行操作。在那之后,它不能做访问对象(非静态成员)的事情。