提问人:Martin Beckett 提问时间:10/8/2008 最后编辑:Jarod42Martin Beckett 更新时间:12/4/2019 访问量:40018
带有空括号的默认构造函数
Default constructor with empty brackets
问:
是否有任何充分的理由表明一组空的圆括号(括号)对于调用 C++ 中的默认构造函数无效?
MyObject object; // ok - default ctor
MyObject object(blah); // ok
MyObject object(); // error
我似乎每次都自动输入“()”。有没有充分的理由不允许这样做?
答:
函数声明使用相同的语法 - 例如函数,不带参数并返回object
MyObject
评论
因为编译器认为它是一个函数的声明,它不带任何参数并返回一个 MyObject 实例。
因为它被视为函数的声明:
int MyFunction(); // clearly a function
MyObject object(); // also a function declaration
评论
object()
main
any_variable_name random_function_name()
int func1()
double func2()
void func3()
我猜,编译器不知道这句话是否:
MyObject 对象();
是一个构造函数调用或函数原型,它声明一个名为 object 的函数,其返回类型为 MyObject,没有参数。
正如多次提到的,这是一个宣言。这是向后兼容性的方式。由于其遗产,C++ 的众多领域之一,它们愚蠢/不一致/痛苦/虚假。
最令人烦恼的解析
这与所谓的“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>{}};
这样一来,就不可能将其解释为函数声明。
评论
extern "C" foo();
std::vector
v
(
std::istream_iterator
ifs
()
ifs
std::istream_iterator
()
std::istream_iterator
istream_iterator
您还可以使用更详细的构造方式:
MyObject object1 = MyObject();
MyObject object2 = MyObject(object1);
在 C++0x 中,这也允许:auto
auto object1 = MyObject();
auto object2 = MyObject(object1);
评论
RVO
从 n4296 [dcl.init]:
[ 注意:
由于初始化程序的语法不允许,因此不是 X 类对象的声明,而是 不带参数的函数的声明并返回 X。这 form() 在某些其他初始化上下文中是允许的(5.3.4, 5.2.3, 12.6.2).
——尾注]()
X a();
评论
正如其他人所说,它是一个函数声明。从 C++11 开始,如果需要查看空的内容,则可以使用大括号初始化,该空内容明确告诉您使用了默认构造函数。
Jedi luke{}; //default constructor
评论
blah
()
MyObject object
MyObject object()
main