【问题标题】:Unique pointer in-class initialization唯一指针类内初始化
【发布时间】:2014-12-03 20:24:16
【问题描述】:

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

【问题讨论】:

  • NSDMI 必须使用 brace-or-equal-initializer
  • @T.C.谢谢,我不知道这是必须的。

标签: c++ c++11 unique-ptr in-class-initialization


【解决方案1】:

非静态数据成员初始化程序 (NSDMI) 必须使用 brace-or-equal-initializer。不允许使用 ( expression-list ) 形式的初始化。

正如N2756 解释的那样,为了让 NSDMI 的行为更像传统的构造函数成员初始化器列表,在整个类的范围内查找初始化器内的名称。不幸的是,这意味着允许使用括号初始化器将无法在解析声明时确定某个东西是初始化器还是函数声明:

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

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

该论文讨论了几种可能的方法来解决这个问题,而不是完全禁止它(“所有可以是声明的东西都是声明”或“它不是类型,除非你说它是类型”),但都不是很吸引人,并且潜在的混乱被认为超过了允许这种初始化形式的好处。

【讨论】:

  • 好点,我认为这可能是某种最令人烦恼的解析问题,但我自己却想不出一个例子。谢谢!
【解决方案2】:

因为这些是规则。类内初始化器必须使用“大括号”或“等号”;事实上,句法元素被称为 brace-or-equal-initializer

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

【讨论】:

  • 谢谢,不知道规则。语法确实挺烦人的,尤其是第二行std::vector&lt;int&gt; good{6};,和大家想的不太一样。
猜你喜欢
  • 2017-07-26
  • 1970-01-01
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 2012-02-13
  • 1970-01-01
  • 2021-08-08
相关资源
最近更新 更多