2014-10-09 49 views
5

假设我有一个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; 
} 
+4

NSDMIs必须使用* brace-equal-initializer *。 – 2014-10-09 02:37:24

+0

@ T.C。谢谢,我不知道这是必须的。 – vsoftco 2014-10-09 02:40:16

回答

7

非静态数据成员的初始值(NSDMI)必须使用支架 - 或等于初始值设定:当有直接和支架初始化之间的差异也可以是恼人的。不允许初始化的(expression-list)形式。

正如N2756所解释的,为了让NSDMIs更像传统的构造函数成员初始化列表,可以在整个类的范围内查找初始化符内部的名称。不幸的是,这意味着允许括号初始化,就不可能确定的东西是否是在当时的声明被解析的初始化或函数声明:

// not real code 
struct X { 
    int i(x); // initializer 
    static int x; 
}; 

struct Y { 
    int i(x); // function 
    typedef int x; 
}; 

本文讨论了几个可能的方式来解决这个短完全禁止它(“可以是声明的所有内容都是声明”或“除非你声明这是一种类型,否则它不是一种类型”),但两者都不具吸引力,并且认为潜在的混淆可能超过允许此表单的好处的初始化。

+0

好点,我认为这可能是某种最令人头痛的解析问题,但无法自己拿出一个例子。谢谢! – vsoftco 2014-10-09 02:44:09

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 
+0

谢谢,不知道规则。语法的确很烦人,特别是第二行'std :: vector good {6};',这不符合人们的想法。 – vsoftco 2014-10-09 02:42:43