3
#include <memory>

struct foo
{
    std::unique_ptr<int> p;
};

int main()
{
    foo bar { std::unique_ptr<int>(new int(42)) };
    // okay

    new foo { std::unique_ptr<int>(new int(42)) };
    // error: no matching function for call to
    // 'foo::foo(<brace-enclosed initializer list>)'
}

统一初始化是否不适用于动态对象,或者这是 g++ 4.6.1 的缺点?


它适用于 g++ 4.7.1,但如果从另一个类继承,则这两行都main无法编译:foo

struct baz
{
    // no data members, just some member functions
};

struct foo : baz
{
    std::unique_ptr<int> p;
};

再次,我的编译器的缺点?或者统一初始化不能很好地与继承一起使用?

4

3 回答 3

4

它使用 g++-4.7 构建良好。所以大概是后者。我会看看是否可以通过文档找到更有力的证据。

并响应继承附录:

这个更简单的情况也无法编译:

struct baz
{
};

struct foo : baz
{
    int b;
};

int main()
{
    foo bar { 12 };
}

和:

testoo.cpp:14:18: error: no matching function for call to ‘foo::foo(<brace-enclosed initializer list>)’
testoo.cpp:14:18: note: candidates are:
testoo.cpp:7:8: note: foo::foo()
testoo.cpp:7:8: note:   candidate expects 0 arguments, 1 provided
testoo.cpp:7:8: note: constexpr foo::foo(const foo&)
testoo.cpp:7:8: note:   no known conversion for argument 1 from ‘int’ to ‘const foo&’
testoo.cpp:7:8: note: constexpr foo::foo(foo&&)
testoo.cpp:7:8: note:   no known conversion for argument 1 from ‘int’ to ‘foo&&’

根据我对标准的阅读,您aggregate initialization在第一个示例中得到了:

聚合是一个数组或类(第 9 条),没有用户提供的构造函数(12.1),没有用于非静态数据成员的大括号或等号初始化程序(9.2),没有私有或受保护的非静态数据成员(第 11 条),没有基类(第 10 条),也没有虚函数(10.3)。

当聚合由初始化列表初始化时,如 8.5.4 中所指定,初始化列表的元素被视为聚合成员的初始化,按递增的下标或成员顺序。

请注意,这明确禁止基类。总而言之 - 在存在基类的情况下不允许聚合初始化。因此,第二个示例都不会编译。

于 2012-07-09T12:23:44.103 回答
2

如果从另一个类继承,则两行都main无法编译foo

啊,统一初始化对于聚合和非聚合的工作方式不同:

类型 T 的对象或引用的列表初始化定义如下:

  • 如果 T 是聚合,则执行聚合初始化
  • [...]
  • 否则,如果 T 是类类型,则考虑构造函数

聚合是 [..] 一个没有基类 [...] 也没有虚函数的类 [...]。

所以我仍然需要编写自定义构造函数,因为我需要这里的子类型多态性。

于 2012-07-09T13:30:53.363 回答
1

我目前没有最终版本,但草案 N3242§ 8.5.4 List-initialization明确指出列表初始化可以用作新表达式中的初始化程序。它还提供了以下示例:

new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements
于 2012-07-09T13:10:41.100 回答