2009-12-18 57 views
2

我有一個C++類層次結構,看起來是這樣的:析構函數爲了

class A; 

class B 
{ 
public: 
    B(A& a) : a_(a) 
    { 
    }; 

private: 
    A& a_; 
}; 

class MyObject 
{ 
public: 
    MyObject() : b_(a_) 
    { 
    }; 

private: 
    A a_; 
    B b_; 
}; 

有時,它會發生在B的析構函數,我會得到有關其A的參考無效訪問異常則顯得在B之前銷燬。

使用類成員初始化其他成員是否有內在錯誤?是否不能保證銷燬的順序?

感謝, PaulH

+1

這是整個代碼,給你毀壞後的段錯誤嗎?你能告訴我們main()嗎? – rui 2009-12-18 16:28:44

+0

問題是編譯器生成的複製構造函數。詳情請參閱下面的答案。 – 2009-12-18 19:04:50

回答

6

編輯:我錯過了你的問題的MyObject一部分,所以我原來的答覆可能不會有很大幫助。我想你的問題在於你沒有發佈的代碼,精簡的例子應該可以正常工作。


B不「自己的」通過引用傳遞的對象,所以對象ab具有不同的生命週期。如果B::a_引用的對象被銷燬,則B的析構函數將訪問無效的引用。

一些代碼來說明我的意思:

class A; 

class B { 
public: 
    B(A a) : a_(a) {} // a is copied to a_ 
    ~B() { /* Access a_ */ } 
private: 
    A a_; 
}; 

class C { 
public: 
    C(A& a) : a_(a) {} // a_ is a reference (implicit pointer) 
         // of an external object. 
    ~C() { /* Access a_ */ } 
private: 
    A& a_; 
}; 


int main(int argc, char** argv) { 
    A* a = new A(); 

    B b(*a); 
    C c(*a); 

    delete a; 
    // Now b has a valid copy of a, c has an invalid reference. 
} 
+0

嗯,你的意思是在B中有一個析構函數對A做了些什麼? – rui 2009-12-18 16:27:25

+1

施工訂單遵循聲明訂單,銷燬訂單逆轉。在MyObject示例中,這意味着a_應該在b_之前構造,並且a_應該在b_之後被銷燬。 IOWs,你說的正確的是,按照定義,B不擁有a_ *,但是,如定義的,MyObject應該保證正確的構造和銷燬順序。 – 2009-12-18 16:29:30

+0

@Eric:你說得對,我錯過了MyObject的細節。 – 2009-12-18 16:33:40

5

A_應該B_之前建造,並應B_ A_之前遭到破壞,根據您在MyObject來定義的順序上。

6

在上面的代碼中,銷燬順序已被很好地定義。
銷燬順序與創建順序相反。
創建順序是成員在班級中聲明的順序。
因此,在這種情況下:

Default Construction: 
    a_: constructed first using default constructor. 
    b_: constructed using a valid a_ passed to the constructor. 

Destruction: 
    b_: destroyed first. The destructor can use the reference to a 
     As long as the object has not been copied (see below) 
    a_: destroyed second. 

但是,如果您使用拷貝構造函數的對象的副本你有一個潛在的問題。

下面的拷貝構造函數是由編譯器定義:

MyObject::MyObject(MyObject const& copy) 
    :a_(copy.a_) 
    ,b_(copy.b_) 
{} 

所以,你可以在這裏有一個潛在的問題。由於副本將包含一個包含從另一個對象複製的引用的對象'b_'。如果另一個對象被破壞,那麼這個'b_'將會有一個無效的引用。