【问题标题】:Constructor interpreted as function call, and move constructors strangly skipped构造函数被解释为函数调用,并且移动构造函数被奇怪地跳过了
【发布时间】:2018-01-11 14:00:59
【问题描述】:

我有一个有 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) { }

请帮我解释一些我觉得奇怪的行为(我使用 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));
}

【问题讨论】:

  • 1 和 2 中的代码 sn-p 完全相同。它必须是int main() 而不是void
  • 您使用的是 C++11 或更高版本吗?
  • 请修复代码“Now if I change to”与之前的代码完全相同的问题
  • 对不起,我已经更正了 sn-p 2。是的,我使用的是 C++14。

标签: c++ constructor move-constructor most-vexing-parse


【解决方案1】:

由于被称为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 是一个不带参数的函数。


对于为什么不调用移动构造函数的问题,我没有答案。

【讨论】:

  • 第二个问题似乎是 OP 错误地使用了与 1 中相同的代码。我猜是 ABC a1(ABC(5)); 而不是
  • 而且似乎 OP 询问为什么缺少移动 ctor 的调用。
  • 我不肯定,但我认为移动构造函数没有被调用,因为编译器可以选择排除它们以提高效率。
  • @R Sahu:非常感谢您对 MVP 的解释。但我仍在等待移动构造函数完成的答案。
猜你喜欢
  • 1970-01-01
  • 2016-07-12
  • 2019-05-27
  • 2017-09-19
  • 2018-06-01
  • 1970-01-01
  • 2011-05-22
  • 2021-08-06
  • 1970-01-01
相关资源
最近更新 更多