2017-08-03 54 views
2

我有4个构造一个类,如下功能:构造解释为函数调用,并移动构造strangly跳过

using namespace std; 

class ABC { 
public: 
    ABC() { 
     cout << "ABC()\n"; 
    } 

    ABC(int) { 
     cout << "ABC(int)\n"; 
    } 

    ABC(ABC&) { 
     cout << "ABC(&)\n"; 
    } 

    ABC(ABC&&) { 
     cout << "ABC(&&)\n"; 
    } 
}; 


void ff(ABC t) { } 

请帮我解释一些行为,似乎很奇怪,我(我用MSVC 2016编译):

1)为什么我会收到警告C4930:''ABC a1(ABC(__cdecl *)(void))':原型函数未调用(是一个变量定义?以下代码:

void main() { 
    ABC a1(ABC()); 
    ff(ABC(5)); 
} 

和执行,我希望能得到以下的输出:

ABC() 
ABC(&&) 
ABC(int) 
ABC(&&) 

但是我真正得到的是

ABC(int) 

2)现在,如果我改变

void main() { 
    ABC a1(ABC(5)); 
    ff(ABC(5)); 
} 

有没有更多的警告。但在执行中,我所期望得到的是

ABC(int) 
ABC(&&) 
ABC(int) 
ABC(&&) 

但是我真正得到的是

ABC(int) 
ABC(int) 

3)现在

void main() { 
    ABC(ABC()); 
    ff(ABC(5)); 
} 

它甚至不能编译。我得到错误C2660:“'ABC':函数不带1个参数”。

4)最后,为什么以下编译时3)不?

void main() { 
    ff(ABC(5)); 
} 
+2

部分问题:https://stackoverflow.com/questions/38951362/most-vexing-parse – NathanOliver

+4

1和2中的代码段完全相同。它必须是'int main()'not'void' – Slava

+1

你使用的是C++ 11还是更高版本? –

回答

5

由于被称为most vexing parse in C++问题,行

ABC a1(ABC()); 

声明a1是一个函数,其返回类型为ABC,其参数类型是一个函数,没有参数和返回ABC


线

ABC(ABC()); 

是较硬的解剖但它也是一个函数的声明,而不是一个变量的定义。

int(a); 

是变量a的有效声明。它是相同:

int a; 

类似地,与ABC线是一样的:

ABC ABC(); 

这里ABC已经过载的意义。第一个ABC是类型名称。第二个ABC是函数名称(由于最棘手的解析)。它声明ABC是一个不带参数并返回ABC类型的对象的函数。对于函数的其余部分,ABC是函数名称,而不是类型名称。因此,

ff(ABC(5)); 

是无效的,因为在这方面ABC是一个函数,它不带任何参数。


我没有回答为什么移动构造函数没有被调用的问题。

+1

第二个问题似乎是OP的错误地使用了与1中相同的代码。我想它是'ABC a1(ABC(5));'而不是 – Slava

+1

似乎OP询问为什么呼叫移动ctor丢失。 – Slava

+0

我并不积极,但我认为移动构造函数没有被调用,因为编译器可以选择排除它们以提高效率。 – Andy