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以及其他无数事情;除了
返回之外,几乎任何东西都可以以及指向
*此
的每一个指针在
删除此之前被清除(或绝对不使用)

作为一般规则,您必须对对象生命周期进行的控制级别非常高,才能使
删除此项
safe,您可以将生存期管理重构为类外部的智能资源所有者,智能资源所有者可能会将其状态保持为
pImpl
,并将其删除。喜欢值类型,并且类型
删除此项永远不能被视为值

标准中没有要求
删除此项对于
虚拟
对象来说是非常危险的,而不是更高的继承倾向


所有
删除此项的类型
应该有一个虚拟析构函数,或者是
final
,以避免继承问题。

当我们不知道在哪个上下文中执行时,如何告诉您是否安全?一般来说,
删除此
是一个坏主意(事实上,可以确定的例外情况可能存在),但如果有疑问,听起来像是一个糟糕(且不安全)的设计决策。也许,如果你解释一下你为什么要这么做,你可以给出一个更明确的答案。(但你也不可避免地听到了做这件事的缺点,老实说,我认为这是理所当然的,因为软件设计通常发生在一种语言的语义内,C++从来就不意味着<代码>删除这个<代码> >。我不这么认为,我会关注<代码> VTAB< <代码>的后面。但我对答案很感兴趣,所以我会留下这篇评论,因为COM对象使用虚拟方法实现接口,
delete this
几乎总是用重写的
IUnknown::Release()
方法编写的,然后我不得不说是的,它是安全的。大量的Microsoft/Windows技术都依赖于它。有很多问题,但vtable不在其中。你应该在发布问题之前进行搜索。这里有一个通常的问题,一个函数是否是虚拟的,这不仅关系到它何时被调用,也关系到它何时返回。请确保这是由new创建的,而不是
new[]
,但这些是必要的标准预防措施,以便
删除此函数即使对于非虚拟对象也是安全的。安全吗?也许,在非常可控的情况下。良好做法?可能不会。你会遇到问题吗?除非代码非常简单,否则是的。请记住,在OO设计中,子类实现自己对虚拟方法的重写,并让其重写方法“调用”超类方法,然后在超类方法返回后执行其他操作是很常见的。如果在超类方法调用期间,他们的this对象从下面被删除,大多数子类方法的作者都会感到非常惊讶,因此他们可能会做一些导致未定义行为或随后崩溃的事情。因此,即使最初正确地实现,“删除这个”也是一个等待发生的错误。@Jeremy-如果继承的函数要执行
删除这个
,那么应该仔细记录这一事实。派生版本只能在调用继承版本之前执行操作。在那之后,它不能做访问对象(非静态成员)的事情。