2017-08-31 61 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