24

你能向我解釋返回值,值的引用和常量引用值之間的區別嗎?C++返回值,引用,常量引用

值:

Vector2D operator += (const Vector2D& vector) 
{ 
    this->x += vector.x; 
    this->y += vector.y; 
    return *this; 
} 

不const引用:

Vector2D& operator += (const Vector2D& vector) 
{ 
    this->x += vector.x; 
    this->y += vector.y; 
    return *this; 
} 

常引用:

const Vector2D& operator += (const Vector2D& vector) 
{ 
    this->x += vector.x; 
    this->y += vector.y; 
    return *this; 
} 

我這是好處嗎?我明白const引用傳遞給函數的意義,因爲您要確保不要修改引用指向函數內部的此值。但是我被返回const引用的含義弄糊塗了。爲什麼返回引用比返回值更好,爲什麼返回const引用比返回非const引用更好?

+3

您的C++書的可能重複 –

回答

16

沒有區別,除非你寫出這樣

(v1 += v2) = v3; 

奇怪的東西。在第一種情況下,分配將是一個暫時的,整體效果將是v1 += v2

在第二種情況下,分配將爲v1,因此總體效果將爲v1 = v3

在第三種情況下,分配將不被允許。這可能是最好的選擇,因爲這種古怪幾乎肯定是一個錯誤。

爲什麼返回參考值比返回值要好?

它可能更有效率:您不必複製對象的副本。

以及爲什麼返回const引用比返回非const引用更好?

您防止古怪像上面的例子中,同時仍然允許少怪異鏈如

v1 = (v2 += v3); 

但是,正如在評論中指出,這意味着你的類型不支持的相同形式(ab)用作內置類型,有些人認爲是可取的。

+1

我認爲'const'優於非const,您不能在'+ ='的結果中調用非const的方法。那麼'(v1 + = v2).non_const_fun();'。我知道這是意見,我認爲它可能看起來有點奇怪,但它確實比'(v1 + = v2)= v3'更有意義。真的有禁止它的一點嗎? – luk32

+2

@ luk32我可以看到很多禁止它的邏輯,但是...內置的'+ ='返回一個可修改的左值,並且返回非const引用是用戶定義類型中最接近的。所以最不驚奇的原則---用戶定義的操作符應該模擬內置的操作符---表示非const引用。 –

+0

但是,'const&'阻止了'v1 = std :: move(v2 + = v3)'實際移動。不知道這是否有趣。 –

5

這與將函數的參數傳遞完全相同。

您希望返回const引用,當您返回一個對象的屬性,而不想在其外面修改該對象的屬性。例如:當您的對象有名字時,您可以使用以下方法const std::string& get_name(){ return name; };。這是最優的方式。您允許對內部屬性進行「只讀」訪問,並且無返回複製。

當您重載操作符時,您應該返回一個可變對象,否則某些通常預期會發揮作用的特定語法會產生錯誤。當你嘗試一些奇怪的鏈接時,這非常重要。

例如選擇3不會像(v1 += v2).non_const_method()工作,同時,下面的:

v1+=v2; 
v1.non_const_method(); 
+0

好吧,它對我來說並不乾淨。所以「const」直接對返回對象有效,所以我們不能調用它的函數級聯。如果我們已經將返回的對象賦給了我們的新對象,它就不再是const了。感謝大家! – Majak

1

正如指出的,但是luk32它只是確保沒有改變被允許通過這個返回的對象功能。 這可以基本上幫助你在編譯時找到你的邏輯錯誤。 假設您確定不會更改對象,並且您的代碼正在更改對象,則可以對其進行跟蹤。它可以被認爲是一個很好的編碼習慣。

2

之間的差異返回的值返回按引用在運行時生效:

當你通過值返回一個對象,拷貝構造函數被調用,在堆棧上創建一個臨時實例。

當您通過引用返回對象時,上述所有操作都不會發生,從而提高了性能。


之間的差異返回按引用回報按恆定參考沒有運行時的效果,簡直是爲了保護你從編寫錯誤代碼。

例如,Vector2D& operator += (const Vector2D& vector),你可以這樣做:

(x+=y)++(x+=y).func()其中funcVector2D類非const函數。

但是對於const Vector2D& operator += (const Vector2D& vector),編譯器將爲任何此類類似的嘗試生成錯誤。

4

值:

由價值迴歸意味着你是返回一個對象的副本。這對課程提出了要求(它必須是可複製的或可移動的)。這意味着對於某些按值返回的類的對象而言可能很昂貴(在RVO或NRVO不工作或關閉的情況下)。這也意味着新對象與其他對象是獨立的(受其設計支配),並且是其自身的價值。這是您可能應該從許多二元運算符(例如+, - ,*等)返回的內容。

非const引用:

你真的返回一個別名的另一個對象。別名是非常量允許您修改別名的對象。這就是你應該從一些一元操作符返回的內容,比如前綴++和 - 和*(取消引用),因爲你通常希望能夠修改返回的對象。

這是操作員>>和操作員< <爲流重載而返回的。這使得運營商的鏈接:

cout << 5 << "is greater then" << 1 << endl; 
cin >> myInt >> myFloat; 

您也可以返回參考*這個時候你要允許的正規方法鏈接是這樣的:

object.run().printLastRunStatistics(); 

常引用:

像上面但是你不能修改別名的對象。當要返回的對象拷貝成本高時,以及在從函數返回後可以確保其存在時,可以使用它來代替按值返回。

這是操作員=通常返回到允許的方式多個分配標準類型支持他們:在操作者使用

a = b = c; 

CONST引用=防止這種用法的(未通過標準型遠支持因爲我記得):

++(a = b); 

如果使用正常參考,將被允許。