2016-11-13 17 views
2

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

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_; 
}; 

C++ Standard defines,对于D类型的对象,其寿命结束时析构函数~D()呼叫开始

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

如果是这样,如果我们修改D的基类子对象(如(2)中所述)是否也适用?

+0

当析构函数〜D()调用开始时,它的生命期结束了!生命终结后!构造函数结束! – Klaus

+0

@Klaus不正确。当析构函数调用*开始时,生命周期结束* – krzaq

+0

@krzaq:我可以用析构函数的所有数据成员完成所有的操作。在结束'}'之前没有任何问题。那么为什么你认为生命终止于析构函数的开始呢? – Klaus

回答

6

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

虽然你说得对,生命周期结束时,析构函数开始,你仍然可以使用对象的方式有限,其定义为:

N4140§3.8 [basic.life/6

类似地,在对象的使用期限已经开始之前,但是在对象将占用的存储之后 已经被分配,或者在对象的使用期终止之后并且在对象占用的存储被重新使用或释放​​之前, 任何引用原始对象的glvalue可以使用,但仅限于 有限的方式。 对于正在施工或破坏的物体,请参阅 [class.cdtor]

和[class.cdtor]:

N4140§12.7 [类。cdtor]/1

对于具有非平凡析构函数的对象,请参阅任何 析构函数 之后的对象的非静态成员或基类完成执行导致未定义的行为。

上面清楚地表明,只有在析构函数完成后,才能触及该对象的成员。

+1

似乎彻底,谢谢。我将重新提出这个问题以便(1)提出一个问题,以免混淆其他观众。 –

2

您显示的任何示例都是未定义的行为。他们完美定义。

类实例一直存在,直到析构函数返回。对象的成员在析构函数被调用之前被销毁,但在它返回之后。因此,在析构函数中修改类的成员完全是犹太教。超类在子类完全被销毁之前不会被销毁,所以修改超类的成员也是很好的。

非常一般来说,一个对象被用下述方法破坏:

  1. 析构函数被调用。
  2. 类别成员被破坏,与其初始构造相反。
  3. 对于对象的超类重复步骤1和2。

(我忽略了虚拟继承,为了简单起见,这里没有关系)。

相关问题