假设我有一个unique_ptr
成员对象,我想在课堂上初始化,请参阅下面的代码。为什么我必须使用统一初始化(花括号)?第二个声明吐出错误,如
so.cpp:10:31: error: expected parameter declarator
std::unique_ptr<Foo> upf2(new Foo);
^
so.cpp:10:31: error: expected ')'
so.cpp:10:30: note: to match this '('
std::unique_ptr<Foo> upf2(new Foo); ^
2 errors generated.
而且我认为这是一个最令人烦恼的解析问题,至少我不相信。
#include <memory>
class Foo
{
};
class Bar{
std::unique_ptr<Foo> upf1{new Foo}; // works fine
// std::unique_ptr<Foo> upf2(new Foo); // error here
};
int main()
{
Bar bar;
}
答案 0 :(得分:9)
因为那些是规则。课堂初始化者必须使用“大括号”或“等于”;事实上,语法元素被称为大括号或等于初始化。
int equals = 42; // OK
std::unique_ptr<Foo> braces{new Foo}; // Also OK
我不知道为什么不允许使用括号;也许是为了避免初始化看起来像函数声明的可能性。当直接初始化和大括号初始化之间存在差异时,这可能很烦人:
std::vector<int> bad(6); // ERROR: parentheses not allowed
std::vector<int> good{6}; // OK but not the same
std::vector<int> ugly = std::vector<int>(6); // OK but ugly
答案 1 :(得分:7)
非静态数据成员初始化程序(NSDMI)必须使用大括号或等于初始化程序。 <{1}}形式的初始化是不允许的。
正如N2756所解释的那样,为了使NSDMI的行为更像传统的构造函数成员初始化程序列表,初始化程序中的名称将在整个类的范围内查找。不幸的是,这意味着允许使用括号初始值设定项将无法在解析声明时确定某些内容是初始化函数还是函数声明:
( expression-list )
本文讨论了几种可能的方法来解决这种完全禁止它的问题(&#34;所有可以作为声明的声明都是声明&#34;或者#34;它不是一种类型,除非你说它是一种类型&#34;),但两者都没有吸引力,并且潜在的混淆被认为超过了允许这种形式的初始化的好处。