2011-03-19 59 views
2

在​​中,當我將一個未命名的A變量傳遞給B的變量時,該變量在行後被破壞。據this answer瞭解對象的壽命時間,範圍,RAII

臨時對象是在充分表達的 最終摧毀他們的 一部分。完整的表達式是一個 表達式,它不是某個其他表達式的子表達式 。通常這個 意味着它結束於; (or) for if, while, switch etc.)表示結束 的聲明。

我得到它,但類B怎麼能知道它的mamber_a變量的值,它被破壞後?我知道A的拷貝是enver被調用的。這怎麼可能?

#include <iostream> 
using namespace std; 

class A 
{ 
     int sign; 
     A(); 
     const A & operator=(const A &); 
public: 
     A(int x) : sign(x) { 
       cout << "A ctor : " << sign << endl; 
     } 

     void WriteA() const { 
       cout << sign << endl; 
     } 

     ~A() { 
       cout << "A dtor : " << sign << endl; 
     } 

     A(const A &) { 
       cout << "A copied : " << sign << endl; 
     } 
}; 

class B 
{ 
     int sign; 
     const A & member_a; 
public: 
     B(const A & aa , int ww) : sign (ww) ,member_a(aa) { 
       cout << "B ctor : " << sign << endl; 
     } 

     void WriteB() const { 
       cout << "Value of member_a :"; 
       member_a.WriteA();  
     } 

     ~B() { 
       cout << "B dtor : " << sign << endl; 
     } 
}; 

int main() { 
     A a(10); 
     B b1(a,1); 
     b1.WriteB();  

     B b2(A(20),2); 
     b2.WriteB(); 

     return 0; 
} 

輸出是:

A ctor : 10 
B ctor : 1 
Value of member_a :10 
A ctor : 20 
B ctor : 2 
A dtor : 20 
Value of member_a :20 // Object A was destructed. Where does this 20 come from? 
B dtor : 2 
B dtor : 1 
A dtor : 10 

回答

5

你的C++

棘手的部分之一,它是純粹的機會member_a的值爲20你打什麼審閱爲未定義的行爲。

當一個類保留對外部對象的引用時,程序員有責任確保該對象的生命週期比所引用的對象的持續時間更長。在這種情況下,當你打電話給member_a.WriteA();時,一個對象已經被銷燬,因此你正在訪問的內存可能不屬於你(在這種情況下,它恰好在附近一個沒有被覆蓋的位置) )。

如果您要保留對對象的引用。您可以保留一個const引用,但有時最好將該參數設置爲正常引用,以便您不會意外傳遞一個臨時值(因爲您可能必須通過引用傳遞const對象,所以這並不總是奏效)。

1

使用對被破壞對象的引用是一個「未定義的行爲」。

在A的析構函數中,嘗試將「sign」設置爲「-1」並查看會發生什麼。賠率是「WriteB」的調用將顯示你已經發送了一個消息給已故的對象。

現在嘗試使用b2的構造函數和b2.WriteB的調用之​​間的代碼堆棧,例如調用子例程。你現在可能會發現這個調用打印出不同的東西。