在构造函数完成合法之前调用析构函数?

Bjö*_*lex 6 c++ constructor destructor asynchronous

假设我有一个类,其构造函数生成一个删除对象的线程:

class foo {
public:
    foo() 
    : // initialize other data-members
    , t(std::bind(&foo::self_destruct, this)) 
    {}

private:
    // other data-members
    std::thread t;
    // no more data-members declared after this

    void self_destruct() { 
        // do some work, possibly involving other data-members
        delete this; 
    }
};
Run Code Online (Sandbox Code Playgroud)

这里的问题是析构函数可能在构造函数完成之前被调用.在这种情况下这是合法的吗?因为t声明(并因此初始化)最后,并且构造函数体中没有代码,并且我从不打算子类化这个类,我假设该对象在self_destruct被调用时已经完全初始化.这个假设是否正确?

我知道delete this;如果this在该语句之后没有使用该语句在成员函数中是合法的.但构造函数在几个方面都很特殊,所以我不确定这是否有效.

另外,如果它是非法的,我不知道如何解决它,其他产生线程的特殊初始化函数必须在构造对象后调用,我真的想避免.

PS:我正在寻找C++ 03的答案(我只限于这个项目的旧编译器).的std::thread只是为了说明,目的在本例中是.

Jos*_*eld 7

首先,我们看到类型的对象foo具有非平凡的初始化,因为它的构造函数是非平凡的(§3.8/ 1):

如果一个对象属于类或聚合类型,并且它或其成员之一由除了普通默认构造函数之外的构造函数初始化,则称该对象具有非平凡的初始化.

现在我们看到类型foo生命周期的对象在构造函数结束后开始(§3.8/ 1):

类型对象的生命周期从以下时间T开始:

  • 获得具有适当对齐和T型尺寸的存储,并且
  • 如果对象具有非平凡的初始化,则其初始化完成.

现在,它是不确定的行为,如果你做delete的构造年底前在对象上,如果该类型foo有一个不平凡的析构函数(第3.8节/ 5):

在对象的生命周期开始之前,但在对象将占用的存储空间被分配之后,可以使用任何指向对象所在或将被定位的存储位置的指针,但仅限于有限的方式.对于正在建造或销毁的物体,见12.7.除此以外, [...]

因此,由于我们的目标正在构建中,我们来看看§12.7:

成员函数,包括虚函数(10.3),可以在构造或销毁期间调用(12.6.2).

这意味着self_destruct在构造对象时调用它是好的.但是,本节没有具体说明在构造对象时销毁对象.所以我建议我们看一下这个的操作delete-expression.

首先,它"将调用被删除对象的析构函数(如果有的话)." 析构函数是成员函数的一个特例,所以可以调用它.但是,§12.4析构函数没有说明在构造期间调用析构函数时它是否定义良好.这里没有运气.

其次," delete-expression将调用释放函数 ","释放函数将释放指针引用的存储".再一次,没有任何关于这样做的存储,目前正在使用的存储是正在构建的对象.

所以我认为这是一个未定义的行为,因为标准没有非常准确地定义它.

需要注意的是:类型对象的生命周期在析构函数调用开始时foo 结束,因为它有一个非平凡的析构函数.因此,如果delete this;在对象构造结束之前发生,它的生命周期在它开始之前结束.这是在玩火.