2014-06-17 77 views
1

我遇到過有關使用參考數據成員的示例源代碼,我對輸出感到困惑。這裏是示例代碼。指向堆棧變量的參考(&)數據成員的行爲

class Test { 
private: 
    int &t; 
public: 
    Test (int y):t(y) { } 
    int getT() { return t; } 
}; 

int main() { 
    int x = 20; 
    Test t1(x); 
    cout << t1.getT() << "\n"; // Prints 20 as output. however y has already been destroyed but still prints 20. 
    x = 30; 
    cout << t1.getT() << endl; // Prints Garbage as output Why ? Ideally both steps should be Garbage. 
    return 0; 
} 

而爲更混亂添加這裏是同一類

int main() { 
    int x = 20; 
    int z = 60; 
    Test t1(x); 
    Test t2(z); 
    cout<<t1.getT()<<"\n"; // Prints 60! WHY? Should print garbage 
    cout<<t2.getT() << "\n"; // Prints Garbage 
    cout<<t1.getT() << endl; // Prints Same Garbage value as previous expression 
    return 0; 
} 

回答

1

現在我明白了。是的,它是未定義的,但要回答我的問題,爲什麼它打印垃圾之前打印20或60?實際上,答案是20和60這兩個值都是垃圾,理想情況下getT函數調用應該打印垃圾,但它不會。因爲Test t2(z); cout<<t1.getT()<<"\n"; 之間沒有其他指令,但對於下一個語句\ n作爲指令並同時堆棧清除值。

2

x一個更一段代碼通過使用臨時值傳遞,所以t一個參考那個臨時的,而不是x。構造函數返回後,該臨時對象將被銷燬。您的代碼有未定義的行爲。任何東西都可以作爲輸出。你的問題可以通過傳遞一個參考x

Test (int& y):t(y); 

來解決,但這不是一個好主意。有些情況下,x超出範圍,但Test對象仍在使用,則會出現相同的問題。

2

你的構造:

Test (int y):t(y) { } 

設定T爲在調用函數爲y的引用,堆棧上的本地(臨時)變量,而不是可變的。當您在調用函數中更改變量值時,它不會更改您創建的對象中的任何內容。

事實上,引用是在構造函數的生命週期結束時丟失的臨時變量,意味着getT()返回一個未定義的值。

int getT()的每次調用都會訪問y的內存地址。該內存地址在構造函數結束時從堆棧釋放,因此它指向不在堆棧或堆中的內存,因此可以隨時重用。重用的時間沒有被定義,並且取決於編譯器和依賴庫所建立的其他操作。因此,int getT()的返回值取決於操作系統上影響內存的其他元素,編譯器類型和版本以及操作系統等。

+0

實際上,我關心的是在y的內存地址上刷新值的時間。在第一個getT語句中,它打印已經被銷燬的地址的值,但仍然打印一些不是垃圾值的值。 – Tejendra

+0

'getT()'會導致未定義的行爲(不只是「返回一個未定義的值」) - 任何事情都可能發生 –

+0

我已經添加了第三段,其中包含一些關於未定義行爲的細節。值得指出的是,在你的例子中,第一個getT()似乎工作,但它仍然是未定義的 - 如果你運行它1000次或運行在另一個操作系統上,你可能會得到不同的結果! – youngthing