2016-11-13 16 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。

(我忽略了虛擬繼承,爲了簡單起見,這裏沒有關係)。

相關問題