在析构函数中修改类成员对象是否会导致未定义的行为?

Leo*_*aar 3 c++ destructor lifetime undefined-behavior language-lawyer

例如:

struct B { int b_; };
struct D : B
{
    ~D()
    { // D object's lifetime ends here
        d_ = 0;  // (1) undefined behavior?
        b_ = 0;  // (2) undefined behavior also?
    }
    int d_;
};
Run Code Online (Sandbox Code Playgroud)

C++标准定义,对于类型的对象D,其寿命结束析构函数时~D()呼叫开始.

我们可以解释这意味着修改析构函数内的对象,如(1)所示,会导致未定义的行为吗?

如果是这样,如果我们修改基类子对象D,如同在(2)中那样适用吗?

krz*_*zaq 7

这两种访问都没有定义,它们都完全没问题.

当析构函数启动时,生命周期结束时你仍然是正确的,你仍然可以用有限的方式使用对象,定义如下:

N4140§3.8[basic.life]/6

类似地,在对象的生命周期开始之前但在对象将占用的存储已经被分配之后,或者在对象的生命周期结束之后并且在对象占用的存储被重用或释放之前,任何引用的glvalue之前可以使用原始对象,但仅限于有限的方式.对于正在构建或销毁的对象,请参阅[class.cdtor].

和[class.cdtor]:

N4140§12.7[class.cdtor]/1

对于具有非平凡析构函数的对象,在析构函数完成执行后引用对象的任何非静态成员或基类会导致未定义的行为.

以上清楚地指出,只有在析构函数完成后,您才能触及该对象的成员.