這些有什麼區別?功能類型之間的區別
MyType myFunction();
MyType t = myFunction();
和
MyType &myFunction();
MyType t = myFunction();
和
const MyType &myFunction();
MyType t = myFunction();
這是怎麼回事幕後?
這些有什麼區別?功能類型之間的區別
MyType myFunction();
MyType t = myFunction();
和
MyType &myFunction();
MyType t = myFunction();
和
const MyType &myFunction();
MyType t = myFunction();
這是怎麼回事幕後?
在這三種情況下,第二行是常見的:
MyType t = myFunction();
這條線得到調用myFunction
的結果,並使用它來拷貝構造的MyType
稱爲t
了新的元素。
現在就分歧。在第一種情況下,您按值返回,這意味着(語義上),編譯器將創建myFunction
中return
語句中的對象的副本,然後將該副本用作t
複製構造的源。編譯器很可能會刪除副本(至少是第二個)。
在另外兩種情況下,函數返回引用到某個其他對象。如果對象是本地人,那麼它是未定義的行爲。兩者之間的區別在於返回的引用是否可以用來修改引用的對象,這可能會影響使用的拷貝構造函數或者它可以被使用。請注意,您從中獲取引用的對象必須超過函數調用,否則您將導致未定義的行爲。
// an example where it matters:
typedef std::auto_ptr<int> MyType;
MyType t = myFunction();
因爲std::auto_ptr
修改分配上右手邊,前面的代碼將僅在返回的引用是非const的工作。
陸points指出,返回參考很可能是未定義的行爲,所以什麼時候它不會?當從中獲得參考的對象超過參考的使用時。這是Meyers單件的基本構建塊:
// an example where returning a reference is correct
MyType & myFunction() {
static MyType instance; // Note static storage duration!
return instance;
}
或者返回對子對象的引用的任何普通存取器。一些常見的情況是容器中的operator[]
(它們通常不會複製值,但會返回對存儲數據的引用)。
但事實上,函數通常不返回靜態生命的對象,而是返回本地。
我假設這些都是免費的功能。
MyType myFunction();
MyType t = myFunction();
由值返回MyType
對象。理論上,myFunction
內部創建的對象在返回時被複制。實際上,RVO很可能會發生。
MyType &myFunction();
MyType t = myFunction();
通過參考返回。這很可能是未定義的行爲,因爲通過引用返回本地對象是非法的。但是,如果myFunctions
是成員函數,則可以返回該類的成員MyType
,只要實例超過t
,就可以。
對於第二個代碼片段,你應該得到一個警告 - 「通過引用返回局部變量」或類似的東西。
@OliCharlesworth是的,對不起。我立即糾正它。 – 2012-03-26 11:28:52
「通過引用返回本地對象是非法的」...所以我應該如何返回在函數內創建的對象? – Cheetah 2012-03-26 11:29:46
@按價值發展 - 就像第一個片段一樣。 – 2012-03-26 11:30:12
我猜你想要做的是一樣的東西:
MyType *myFuntion()
{
MyType *t = new MyType;
// do something with t
return t;
}
// ... somewhere else ...
MyType *t = myFunction();
即構造一個函數內一個新的對象,並返回一個指向它。別忘了打電話
delete t;
以後某個地方!
大多數答案都是正確的,除了一個小的細節。
const MyType& t = myFunction();
看起來,如果myFunction()返回一個臨時變量,這將是未定義的行爲,但事實上並非如此。這不是UB,事實上,const引用將臨時的生命週期擴展到const引用的生命週期。事實上,這是編譯器優化最具潛力的版本,並且還提供了一個重要的教訓,即在可能的情況下應始終將返回值返回到const引用。
我不確定你在說什麼。如果'myFunction()'返回一個值,那麼它是一個臨時的。總是。儘管臨時(或C++ 03中的副本)的生命週期可能會延長,但絕對沒有理由不在這裏使用MyType t = myFunction()。如果'myFunction()'返回一個引用,那麼它是未定義的行爲,不管你如何處理返回值。 – 2012-03-26 12:40:55
事後看來,我發現我是個傻瓜,因爲我錯過了函數sig。但基本上如果'MyType myFunction();'然後'const MyType&t = myFunction();'是有效和首選的。'MyType t = myFunction();'帶有上面的簽名更可能做一個經常不必要的臨時(沒有進入RVO和NRVO的細節)。 – Ylisar 2012-03-26 12:48:16
或多或少。如果'myFunction()'按值返回,沒有意義不使用它來初始化一個值;使局部變量成爲參考類型只是額外的噪音。如果'myFunction()'返回一個引用,允許對象(其他地方存在)的多態性或(如果非const)修改,那麼使用本地引用很容易,以避免每次調用該函數訪問該對象。 – 2012-03-26 12:53:20
除了Meyers單例(由於各種原因,它不享受通用粘連),您可能會在'std :: vector'和'std :: map'中使用'[]'運算符等網站功能。它們可能是更常用的返回值引用的示例。 – 2012-03-26 12:37:32
@JamesKanze:對,應該返回引用的類中有許多*訪問器*。我試圖限制對免費函數的迴應,因爲這似乎是問題的情況。將更新答案以包含該特定示例。謝謝。 – 2012-03-26 13:12:05