【问题标题】:"delete this" in constructor在构造函数中“删除这个”
【发布时间】:2011-07-15 06:53:29
【问题描述】:

当我执行这段代码时实际发生了什么?

class MyClass
{
    MyClass()
    {
        //do something
        delete this;   
    }
}

【问题讨论】:

  • 这是一个真正的问题,因为我需要创建类似“僵尸线程”的东西,它包含在一个类中,该类会在线程完成执行之前自行删除。
  • 如果这就是您要找的东西,那么请询问 that,Uray,而不是 this
  • 我认为这是一个有趣的问题。
  • @Rob:如果我问这个问题,我永远不会知道这样做的后果是什么,直到它变成一个错误。我的实际实现并不是我需要问的问题。
  • @Hans “基于您面临的实际问题”。我怀疑这是一个明智的标准。

标签: c++ constructor destructor delete-operator self-destruction


【解决方案1】:

假设您的对象永远不会被任何东西继承,这应该可以正常工作。您的构造函数运行,然后立即调用析构函数。如果有任何东西继承了这个对象,它将中断,因为这个构造函数将在继承构造函数之前被调用。

【讨论】:

  • 构造函数会在调用析构函数之前“完成”吗?在构造函数中调用析构函数(隐式通过delete)会导致UB吗?
  • @tloach- 我可能是错的,但我相信这会导致未定义的行为(见我的回答)。如果我不正确,请告诉我,我将删除我的反对票。
  • 如何制作一个不能被继承的类呢?
  • @uray 将构造函数设为私有。
【解决方案2】:

注意:此答案适用于 C++03,并且似乎在 C++11 及更高版本中行为已更改,因此现在这是未定义的行为。

事实证明,在这种特殊情况下,代码是合法的,但您远离未定义的行为。

C++03 标准将对象的“生命周期”定义为构造函数完成运行与析构函数开始运行之间的时间。它还明确指出(在 §3.8/5 中)

在对象的生命周期开始之前 [...] 如果对象将是或曾经是具有非平凡析构函数的类类型,并且指针用作删除表达式的操作数,则程序有未定义的行为。

由于对象的生命周期直到构造函数完成才开始,因此在构造函数内部,您引用的 this 指针尚未开始其生命周期,在这种情况下尝试 delete 它是完全安全的。但是,如果您为该类编写析构函数,那么您将立即在此处遇到未定义的行为。

此外,如果您更改构造函数以便在删除对象后尝试引用任何类的数据成员,您将获得未定义的行为。如果对象是在堆栈上分配的,您将获得未定义的行为。如果对象是静态的,您将获得未定义的行为。如果对象是使用new 分配的,那么客户端将返回到它的指针将是无效的,并且使用它会导致未定义的行为。一般来说,不要尝试这样做!

【讨论】:

  • 但是对象必须已经存在,因为在初始化列表完成后调用构造函数,这意味着分配了内存空间并初始化了this指针(因为您可以使用*this作为参数在初始化列表中)。
  • @tloach- 我认为“指针已设置为指向某物”和“指针指向的对象已完全构建”之间存在差异。你可以有一个指向未构造内存的指针;例如,您可以将malloc(sizeof(T)) 类型转换为T* 以获得这样的指针。问题更多的是因为对象还没有开始它的生命周期,所以破坏它的行为是不确定的。
  • 但是这种类型实际上没有一个重要的析构函数。那我们会脱身吗? :-)
  • @Bo:呵呵,我怀疑技术上仍然没有。如果不出意外,这意味着调用new 的人将使用无效的指针值(通过将其复制到某个东西,如果只是作为新表达式结果的临时值)。使用已删除的指针值是标准中的 UB,尽管它不会在我所知道的任何实现中导致任何不好的事情发生。
  • IMO,该段是否适用值得怀疑。这些规则并不适用于正在建设的课程。有一个问题报告,C++0x 修复了文本以插入“对于正在构建或销毁的对象,请参阅 12.7。否则...”
【解决方案3】:

在这里我想了解的第一件事是为什么你想做这样的事情?

构造函数是一个成员函数你的对象实际上是在其中构造的,一旦对象完全构造,你就可以删除它,这就是为什么要做这样的事情 -

class A
{
public:
    A()
    {
        delete this;
    }

    ~A()
    {
    }
};

导致未定义的行为

另外,补充一点,如果你在析构函数中执行delete this,这也是不正确的,因为对象本身正在被销毁,而在析构函数中执行delete this将再次调用析构函数。

class A
{
public:
    A()
    {
    }

    ~A()
    {
        delete this;   // calls the destructor again. 
    }
};

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-04-12
    • 2013-08-19
    • 2021-04-12
    • 2018-10-11
    • 2016-01-27
    • 2012-07-24
    • 2012-09-01
    相关资源
    最近更新 更多