2013-08-23 35 views
6

目前,我正在閱讀有關C++,和我讀了使用引用返回時,我應該確保我不是一個變量,走出去的範圍時,函數返回的迴歸。爲什麼返回一個自動變量工作的引用?

那麼爲什麼在Add函數中,對象cen是通過引用返回的,並且代碼工作正常?

下面是代碼:

#include <iostream> 
using namespace std; 

class Cents 
{ 
private: 
int m_nCents; 

public: 
Cents(int nCents) { m_nCents = nCents; } 

int GetCents() { return m_nCents; } 
}; 

Cents& Add(Cents &c1, Cents &c2) 
{ 
    Cents cen(c1.GetCents() + c2.GetCents()); 
    return cen; 
} 

int main() 
{ 
    Cents cCents1(3); 
    Cents cCents2(9); 
    cout << "I have " << Add(cCents1, cCents2).GetCents() << " cents." << std::endl; 

    return 0; 
} 

我使用的代碼塊IDE對Win7。

+6

因爲它是不確定的行爲,它可以顯示工作正常,但再破以後,它不能依賴。 –

+3

什麼可能發生的(再次,與UB,任何事情都會發生)是因爲你所謂的後'Add',你也沒有告訴其他任何東西,什麼都還沒有覆蓋的一片內存,'cen'了,所以老價值仍然存在。這就是說,你不能依賴那種總是發生的事情。 –

+2

這兩個註釋應該可能是答案 –

回答

7

這是undefined behavior,它可能看起來正常工作,但它可以在任何時候打破,你不能靠這個方案的結果。

當函數退出,用來存放自動變量的內存將被釋放,這將是無效的指代內存。

草案C++標準中部分3.7.3第1段說:

塊範圍變量顯式聲明寄存器或不顯式聲明static或extern具有自動存儲的持續時間。 這些實體的存儲會一直存在,直到它們創建的塊退出。

1

什麼可能發生的(再次,與UB,任何事情都會發生)是因爲你叫Add後,你也沒有告訴其他任何東西,什麼都還沒有覆蓋的一片內存,cen是,所以舊值仍然在那裏。這就是說,你不能依賴那種總是發生的事情。

+0

而@GaryWalker在他的評論中稱,在「Add」和「打印」之間調用任何使用大量堆棧的東西;你幾乎肯定會得到垃圾。 –

+0

實際上,在嘗試使用懸掛參考後,您完全不能依賴任何東西。 – Ruslan

1

您應該執行memcpy以將返回的對象複製到堆。儘管代碼有效,但在返回超出範圍的對象時,行爲未定義。它在代碼很小時總是可以工作,因爲當函數返回時,函數佔用的堆棧部分不會被清除,並且由於函數中的局部變量已經被分配了空間,所以你得到的值(通常)包含您期望的值。但是當你有多個函數互相調用並且程序增長很大時,你的程序就會開始產生未定義的行爲。有時甚至可能出現分段故障。

相關問題