2017-08-31 77 views
0

參照以下代碼:C++函數和右值混亂

// Example program 
#include <iostream> 
#include <string> 
using namespace std; 

struct S 
{ 
    S() 
    { 
     cout << "ctor\n"; 
    } 
    S(S&& rhs) 
    { 
     cout << "called move\n"; 
    } 
}; 

S goo() 
{ 
    S a; 
    return a; 
} 

int main() 
{ 

S&& goo(); 
cout << "before construction\n"; 
S a = goo(); 

} 
//http://thbecker.net/articles/rvalue_references/section_05.html 

爲什麼是代碼調用move constructor而不是功能S goo()?如果你註釋掉第一行,那麼它不會。

爲什麼S goo()的返回類型根據main的第一行而不同?我不認爲這甚至應該編譯,但這裏編譯 http://cpp.sh/22zeq

(上wandbox不會編譯:https://wandbox.org/permlink/3YxBdcWs91FRiODG

在閱讀這裏的例子:http://thbecker.net/articles/rvalue_references/section_05.html 當我偶然發現了這個

+4

你覺得呢'S &&咕();在主'呢? – SergeyA

+0

@SergeyA這裏沒有'S && goo()'的定義,所以它是如何工作的? – PYA

回答

1

這是因爲S&& goo();正在申報新功能。 但是,當你編譯時,它只存在一個名字爲S goo();的函數,這就是它被調用的原因。

這是鏈接的作品。它並沒有發現任何與該名稱的另一個功能,它鏈接到S goo();

+0

'S && goo()'沒有定義,所以它是如何工作的? – PYA

+0

@pyjg這很容易。在這個調用符號名稱goo的地方添加了函數編譯器的調用。然後,鏈接器嘗試通過簽名找到一個函數並找到S goo(),然後用此函數的地址替換它。這個問題是因爲返回值不是功能 –

+0

簽名的一部分@pyjg這是因爲編譯器是另一種功能,但對於連接器只存在一個這樣的函數'咕()'['S咕()'] –

1

返回類型是不同的,因爲S&& goo();函數聲明。所以,它不構成任何東西

它告訴編譯器,goo是一個返回S&&並且不帶參數的函數。這將覆蓋任何其他先前的聲明,因此,對於main函數,goo返回S&&。當你註釋該行時,只有函數定義定義了返回類型。

這也適用於Ideone。也就是在main之內,返回類型goo已更改爲S&&

2

因爲大家似乎在理解S&& goo();在主要做(它聲明一個函數),但人們似乎不知道如何調用S goo()到最後。

這樣做的原因是,返回值不是函數簽名的一部分的事實。因此,當您致電goo()時,您最終會調用唯一可用的版本 - 一個返回S。我相信,這是未定義行爲的一個例子。

+0

謝謝你的答案。不應該這是一個錯誤? – PYA

+0

@pyjg你的代碼有bug嗎?我相信,它是。 – SergeyA

+1

@SergeyA不,我相信OP指的是編譯器如何讓這種模糊的過載甚至被聲明。它可以在另一個翻譯單元中定義是的,但首先它不可行。鏗鏘拒絕代碼正確https://wandbox.org/permlink/pwYSWrxoHNLEDOs6 – Curious