例如:
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_;
};
当析构函数D
调用启动时,对于类型为~D()
的对象,其生命周期结束的C++ Standard defines。< / p>
我们能否解释这意味着修改析构函数内的对象(如(1)中)会导致未定义的行为?
如果是这样,如果我们修改D
的基类子对象,如同在(2)中那样适用吗?
答案 0 :(得分:7)
两种访问都没有定义,它们都完全没问题。
虽然你的生命周期在析构函数启动时结束是正确的,但你仍然可以用有限的方式使用对象,定义如下:
N4140§3.8[basic.life] / 6
同样,在一生之前 对象已经开始但是在对象占用的存储之后 已经分配,或者在对象的生命周期结束后 在重用或释放对象占用的存储之前, 可以使用任何引用原始对象的glvalue,但仅限于 有限的方式。 对于正在建造或毁坏的物体,请参阅 [class.cdtor]
和[class.cdtor]:
N4140§12.7[class.cdtor] / 1
对于具有非平凡析构函数的对象,请参阅any 析构函数后的对象的非静态成员或基类 完成执行导致未定义的行为。
以上清楚地说明,只有在析构函数完成后才能触及该对象的成员。
答案 1 :(得分:2)
您展示的所有示例都不是未定义的行为。它们是完美定义的。
在析构函数返回之前,类实例一直存在。对象的成员不会在析构函数被调用之前被销毁,而是在它返回之后被销毁。因此,在析构函数中修改类的成员是完全犹太的。并且在子类被完全销毁之前,超类不会被破坏,所以修改超类的成员也是完美的。
一般来说,对象会被以下过程破坏:
(为了简单起见,我忽略了虚拟继承,这里没有关系。)