构造函数被解释为函数调用,并且直接跳过了构造函数

kie*_*ien 2 c++ constructor most-vexing-parse move-constructor

我有一个包含4个构造函数的类,函数如下:

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) { }
Run Code Online (Sandbox Code Playgroud)

请帮我解释一些对我来说很奇怪的行为(我使用MSVC 2016进行编译):

1)为什么我收到警告C4930:"'ABC a1(ABC(__ cdecl*)(void))':未调用prototyped函数(是一个变量定义?)",使用以下代码:

void main() {
    ABC a1(ABC());
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

在执行时,我希望得到以下输出:

ABC()
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)

但我真正得到的是

ABC(int)
Run Code Online (Sandbox Code Playgroud)

2)现在,如果我改为

void main() {
    ABC a1(ABC(5));
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

没有更多的警告.但在执行时,我期望得到的是

ABC(int)
ABC(&&)
ABC(int)
ABC(&&)
Run Code Online (Sandbox Code Playgroud)

但我真正得到的是

ABC(int)
ABC(int)
Run Code Online (Sandbox Code Playgroud)

3)现在

void main() {
    ABC( ABC() );
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

它甚至不编译.我得到错误C2660:"'ABC':函数不带1个参数".

4)最后,为什么以下编译而3)没有?

void main() {
    ff(ABC(5));
}
Run Code Online (Sandbox Code Playgroud)

R S*_*ahu 5

由于这个问题被称为C++中最令人烦恼的解析,所以该行

ABC a1(ABC());
Run Code Online (Sandbox Code Playgroud)

声明a1是一个返回类型ABC为的函数,其参数类型是一个不带参数并返回的函数ABC.


这条线

ABC(ABC());
Run Code Online (Sandbox Code Playgroud)

是一个更难解剖,但它也是一个函数的声明,而不是变量的定义.

int(a);
Run Code Online (Sandbox Code Playgroud)

是变量的有效声明a.它与:

int a;
Run Code Online (Sandbox Code Playgroud)

同样,该行与以下ABC相同:

ABC ABC();
Run Code Online (Sandbox Code Playgroud)

这里ABC有重载的含义.第一个ABC是类型名称.第二个ABC是函数名称(由于最令人烦恼的解析).它声明ABC是一个不带参数的函数,并返回一个类型的对象ABC.对于函数的其余部分,ABC是函数名称,而不是类型名称.所以,

ff(ABC(5));
Run Code Online (Sandbox Code Playgroud)

是无效的,因为在该上下文中ABC是一个不带参数的函数.


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