2015-10-20 32 views
2

我有兩段代碼:C++:這種情況下引用的優點是什麼?

int f1(int b) 
{ 
    return b; 
} 

int & f2(int b) 
{ 
    return b; 
} 

是這些功能之間的區別?我知道第二個函數返回一個引用,但是因爲我可以用同樣的方法使用這兩個函數,有什麼區別?

編輯:這個功能更好嗎?

int && f2(int b) 
{ 
    return b; 
} 

什麼時候應該使用返回引用的函數?

Edit2:那麼我什麼時候應該使用返回Rvalue引用的函數呢?

+5

第二個函數暴露未定義的行爲。 –

+0

'因爲我可以同時使用這兩個函數。# – deviantfan

+0

int &&將是一個移動操作。不是你想要的,可能不是語義上正確的。在這裏閱讀:http://stackoverflow.com/questions/4148341/is-this-correct-usage-of-c-move-semantics – user4581301

回答

4

考慮一個簡單的類,它包裝一個數組僅僅是爲了提供一個OP可以對返回的引用做什麼的例子。

class example 
{ 
private: 
    int array[]= {1,2,3,4,5,6,7,8,9,0}; 
public: 
    int get(int index) 
    { 
     return array[index]; 
    } 
    int & get2(int index) 
    { 
     return array[index]; 
    } 
} 

現在我們不會進入未定義行爲的荒地,並可以告訴你這個全副武裝和操作參考電源的例子。

說我們有

example x; 

我們可以調用獲取函數來檢索值

int val1 = x.get(1); 
int val2 = x.get2(2) 

,但我們也可以

x.get2(3) = 30; 

因爲get2返回一個引用,我們可以分配到它並使任務堅持下去。

這是非常寶貴的,你應該想的索引操作符添加到例如

int & operator[](int index) 
{ 
    return array[index]; 
} 

,因爲它允許預期的陣列行爲

int val = x[5]; 
x[6] = 10; 

編輯

託尼·d帶來了另一個重要特徵。返回參考參考。除了允許修改返回的對象之外,這不會創建副本並保存進行副本所耗費的任何努力。對於整數的例子,這是沒有意義的。傳遞一個整數和一個整數的引用的代價要麼相同要麼相近,以至於無關緊要。對於一個更大,更復雜的對象來說,情況並非如此,這可能需要大量的努力才能進行復制或者無法複製或不應複製的對象。

BigFreakingObject & getBigFreakingObject(); 

將允許呼叫者,而不會產生重複它的成本上BigFreakingObject操作。然而,這將交給王國的鑰匙,並允許來電者對BigFreakingObject做任何BigFreakingObject的許可將允許,這可能與BigFreakingObject的所有者的要求相沖突。

聲明與

const BigFreakingObject & getBigFreakingObject(); 

BigFreakingObject const & getBigFreakingObject(); 

參考作爲const將提供一個BigFreakingObject基準但不允許呼叫者來修改它的狀態,保護的BigFreakingObject所有者從任何不愉快的驚喜。

欲瞭解更多詳情,請撥打read up on Const Correctness

+0

我明白。但是,請你告訴我這個表達式有什麼問題:x.get1(3)= 30; ?爲什麼不堅持?如果數組不是私有的,我可以寫數組[3] = 30,它會堅持。 – user2738748

+1

'get1'正在返回值,所以它不返回數組[3]。它返回一個數組[3]的副本。編譯器會抓住這一點,並在你嘗試修改它時發出警告,但如果編譯器確實允許它,你所要做的就是改變一個副本的值。原文將不變。 – user4581301

+0

對於我來說,無論如何,對setter和getter方法的大加法是允許驗證。對象是自衛。例如,如果索引小於0或大於9,我可以將範圍檢查添加到任一get方法並引發異常。對於setter,對象可以防止外人更改其狀態,或者至少在狀態改變了。對於公共變量,對象沒有這種保護。 – user4581301

6
int f1(int b) { 
    return b; 
} 

返回整數b。

int & f2(int b) { 
    return b; 
} 

返回對函數返回時被銷燬的整數b的引用。換句話說,您將值b傳遞給函數,這意味着b在函數的堆棧框架中有一個地址。一旦函數返回,該函數棧幀中的任何內容(包括返回引用的b)都不再存在。所以,你不知道這個參考實際是指什麼,所以你不能使用它。

編輯:您編輯的功能並不好。這將是更正確的:

int& f2(int& b) { 
    return b; 
} 

除非你有這樣的例子@ user4581301給了一個情況,你永遠不應該返回引用你是從,對上述原因返回函數裏創建的對象!

如果你想傳遞一個對象的功能,並有功能做一些該對象而沒有使對象的副本,請執行下列操作:

void f2(int& b) { 
    ... do stuff to b 
} 
+0

如何當該函數是一個類的成員,並返回一個引用一個字段也是這個班的成員? – user2738748

+1

你的例子有一個函數返回一個修改引用的引用並不完全沒有意義。一個類似的習慣用法的例子是ostream&operator <<(ostream&,...)。我也可以想到其他的例子。 –

+0

謝謝。我編輯它指向@ user4581301的例子,這是一個很好的例子! –

3

在...

int & f2(int b) 
{ 
    return b; 
} 

...參數b是調用方提供值的自動(堆棧託管)副本:f2返回堆棧空間被回收時。在返回int&時,即使內存可供重用,您也會傳回對f2b變量的引用。如果您嘗試使用返回的引用來訪問該值,則會出現未定義的行爲。

相關問題