为什么不能用空括号调用默认构造函数?

问题描述 投票:0回答:9

是否有任何充分的理由表明一组空的圆括号(圆括号)对于调用 C++ 中的默认构造函数无效?

MyObject  object;  // ok - default ctor
MyObject  object(blah); // ok

MyObject  object();  // error

我似乎每次都会自动输入“()”。有充分的理由不允许这样做吗?

c++ constructor default-constructor c++-faq most-vexing-parse
9个回答
193
投票

最令人烦恼的解析

这与所谓的“C++ 最令人烦恼的解析”有关。基本上,任何可以被编译器解释为函数声明的东西都将被解释为函数声明。

同一问题的另一个实例:

std::ifstream ifs("file.txt");
std::vector<T> v(std::istream_iterator<T>(ifs), std::istream_iterator<T>());

v
被解释为具有 2 个参数的函数声明。

解决方法是添加另一对括号:

std::vector<T> v((std::istream_iterator<T>(ifs)), std::istream_iterator<T>());

或者,如果您有 C++11 和列表初始化(也称为统一初始化)可用:

std::vector<T> v{std::istream_iterator<T>{ifs}, std::istream_iterator<T>{}};

这样,它就不可能被解释为函数声明。


126
投票

因为它被视为函数的声明:

int MyFunction(); // clearly a function
MyObject object(); // also a function declaration

52
投票

函数声明使用相同的语法 - 例如函数

object
,不带参数并返回
MyObject


11
投票

因为编译器认为这是一个不带参数并返回 MyObject 实例的函数声明。


7
投票

我猜,编译器不会知道这个语句:

MyObject 对象();

是一个构造函数调用或函数原型,声明一个名为 object 的函数,返回类型为 MyObject 并且没有参数。


7
投票

您还可以使用更详细的构造方式:

MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);

在 C++0x 中,这也允许

auto
:

auto object1 = MyObject();
auto object2 = MyObject(object1);

5
投票

正如多次提到的,这是一个声明。这是为了向后兼容。 C++ 中由于其遗留问题而显得愚蠢/不一致/痛苦/虚假的众多领域之一。


5
投票

来自 n4296 [dcl.init]:

[ 注意:
由于

initializer
的语法不允许使用 ()
X a();
不是类 X 的 object 的声明,而是 声明不带参数并返回 X 的function。 form () 在某些其他初始化上下文中是允许的(5.3.4, 5.2.3、12.6.2)。
—尾注]

C++11 链接
C++14 链接


3
投票

正如其他人所说,它是一个函数声明。从 C++11 开始,如果您需要查看空的 something ,明确告诉您使用了默认构造函数,则可以使用大括号初始化。

Jedi luke{}; //default constructor
© www.soinside.com 2019 - 2024. All rights reserved.