2012-05-29 56 views
7

我有下面的類:參考和析構函數在C++

class A 
{ 
public: 
    B& getB() {return b;}  
private: 
    B b; 
}; 

class B 
{ 
    ~B() {cout<<"destructor B is called";} 
... 

}; 

void func() 
{ 
    A *a = new a; 
    B b = a->getB(); 
    ..... 
} 

爲什麼離開函數func當類B的析構函數?函數getB返回一個對象B的參考嗎?如果類A仍然存在於函數func的末尾,爲什麼B的析構函數被調用?

+0

您的b對象仍然是函數的本地對象。 –

回答

6

B b = a->getB(); 

B類型的新對象被創建從對BB&)的現有實例的引用。它不是B::operator=這裏被稱爲複製構造函數

每個類都有一個拷貝構造函數(如果你沒有明確地添加它,編譯器會爲你提供一個)。它接受一個參數,它是對同一個類的引用。你還沒有把拷貝構造函數在上面的代碼,所以我認爲編譯器產生了一個給你:

class B 
{ 
public: 
    B(B& other) 
    { 
     // memberwise copy (shallow copy) 
    }; 
}; 

所以A::getB()退還給會員A::b參考,了此引用作爲參數傳遞B::B(B&)

void func() 
{ 
    A *a = new A(); // Instance of A is created on the heap; 
        // (pointer a is a local variable and is on the stack though!) 
        // A::b is object of type B and it is on the heap as well 

    B b = a->getB(); // Instance of class B is created on the stack (local variable) 
    ..... 
    delete a;  // deleting A from the heap: 
        // A::~A is called which calls B::~B (of its member b) 
} // a and b go out of the scope; b is an object => B::~B is called      
+0

那麼如果創建一個新對象,那麼通過函數的引用返回什麼呢? – Shay

+0

@Shay:該對象是通過引用返回的,所以它避免了在按值返回時的對象副本,但是此返回的引用被複制以在堆棧上創建一個新對象,然後使用返回的引用對其進行初始化。 –

20
B b = a->getB(); 

將調用拷貝構造函數B(const& B)所以你在棧上創建一個新的物體是由參考返回的對象的副本。 改用:

B& b = a->getB(); 

,沒有析構函數將被調用,因爲當你有,你就不會創建一個新的B對象

+0

參考文獻的副本是指B地址的副本嗎? – Shay

+0

@chaiy不這麼認爲,你只是調用複製構造函數 – lezebulon

+2

@Shay不,這個答案是誤導性的。它意味着*對象*的副本。 –