2012-03-26 88 views
2

這些有什麼區別?功能類型之間的區別

MyType myFunction(); 

MyType t = myFunction(); 

MyType &myFunction(); 

MyType t = myFunction(); 

const MyType &myFunction(); 

MyType t = myFunction(); 

這是怎麼回事幕後?

回答

3

在這三種情況下,第二行是常見的:

MyType t = myFunction(); 

這條線得到調用myFunction的結果,並使用它來拷貝構造MyType稱爲t了新的元素。

現在就分歧。在第一種情況下,您按值返回,這意味着(語義上),編譯器將創建myFunctionreturn語句中的對象的副本,然後將該副本用作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[](它們通常不會複製值,但會返回對存儲數據的引用)。

但事實上,函數通常不返回靜態生命的對象,而是返回本地。

+0

除了Meyers單例(由於各種原因,它不享受通用粘連),您可能會在'std :: vector'和'std :: map'中使用'[]'運算符等網站功能。它們可能是更常用的返回值引用的示例。 – 2012-03-26 12:37:32

+0

@JamesKanze:對,應該返回引用的類中有許多*訪問器*。我試圖限制對免費函數的迴應,因爲這似乎是問題的情況。將更新答案以包含該特定示例。謝謝。 – 2012-03-26 13:12:05

1

我假設這些都是免費的功能。

MyType myFunction(); 
MyType t = myFunction(); 

由值返回MyType對象。理論上,myFunction內部創建的對象在返回時被複制。實際上,RVO很可能會發生。

MyType &myFunction(); 
MyType t = myFunction(); 

通過參考返回。這很可能是未定義的行爲,因爲通過引用返回本地對象是非法的。但是,如果myFunctions是成員函數,則可以返回該類的成員MyType,只要實例超過t,就可以。

對於第二個代碼片段,你應該得到一個警告 - 「通過引用返回局部變量」或類似的東西。

+0

@OliCharlesworth是的,對不起。我立即糾正它。 – 2012-03-26 11:28:52

+0

「通過引用返回本地對象是非法的」...所以我應該如何返回在函數內創建的對象? – Cheetah 2012-03-26 11:29:46

+0

@按價值發展 - 就像第一個片段一樣。 – 2012-03-26 11:30:12

-1

我猜你想要做的是一樣的東西:

MyType *myFuntion() 
{ 
    MyType *t = new MyType; 
    // do something with t 
    return t; 
} 

// ... somewhere else ... 
MyType *t = myFunction(); 

即構造一個函數內一個新的對象,並返回一個指向它。別忘了打電話

delete t; 

以後某個地方!

0

大多數答案都是正確的,除了一個小的細節。

const MyType& t = myFunction(); 

看起來,如果myFunction()返回一個臨時變量,這將是未定義的行爲,但事實上並非如此。這不是UB,事實上,const引用將臨時的生命週期擴展到const引用的生命週期。事實上,這是編譯器優化最具潛力的版本,並且還提供了一個重要的教訓,即在可能的情況下應始終將返回值返回到const引用。

+0

我不確定你在說什麼。如果'myFunction()'返回一個值,那麼它是一個臨時的。總是。儘管臨時(或C++ 03中的副本)的生命週期可能會延長,但絕對沒有理由不在這裏使用MyType t = myFunction()。如果'myFunction()'返回一個引用,那麼它是未定義的行爲,不管你如何處理返回值。 – 2012-03-26 12:40:55

+0

事後看來,我發現我是個傻瓜,因爲我錯過了函數sig。但基本上如果'MyType myFunction();'然後'const MyType&t = myFunction();'是有效和首選的。'MyType t = myFunction();'帶有上面的簽名更可能做一個經常不必要的臨時(沒有進入RVO和NRVO的細節)。 – Ylisar 2012-03-26 12:48:16

+1

或多或少。如果'myFunction()'按值返回,沒有意義不使用它來初始化一個值;使局部變量成爲參考類型只是額外的噪音。如果'myFunction()'返回一個引用,允許對象(其他地方存在)的多態性或(如果非const)修改,那麼使用本地引用很容易,以避免每次調用該函數訪問該對象。 – 2012-03-26 12:53:20

相關問題