【问题标题】:uniform initialization for dynamic objects动态对象的统一初始化
【发布时间】:2012-07-09 12:21:52
【问题描述】:
#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,但如果foo 继承自另一个类,则main 中的两行 都无法编译:

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

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

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

【问题讨论】:

  • new foo ({std::unique_ptr&lt;int&gt;(new int(42))}); 这适用于 4.6.1
  • @jrok 这是否意味着我使用的语法(没有额外的括号)在某种程度上是劣质的、非惯用的甚至是“错误的”?
  • 前段时间有一个类似的问题,但是没找到。 IIRC,结论是这是一个错误。

标签: c++ c++11 initialization unique-ptr uniform-initialization


【解决方案1】:

使用 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 中,初始化列表的元素被视为 聚合成员的初始化器,增加下标 或会员订单。

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

【讨论】:

  • 理论上这可能是一种回归。但是,是的,不太可能。
  • @KonradRudolph 好点。我试图在 g++ 发行说明中找到一些关于此的文档,但到目前为止无济于事。
  • @Alex 我在我的问题中添加了另一个转折,以防你感兴趣;)
  • @FredOverflow:我已经尽我所能解析了标准,并想出了一个答案...... :-)
【解决方案2】:
如果foo 继承自另一个类,则main 中的

两行都无法编译

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

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

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

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

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

【讨论】:

  • 所以,列表初始化和统一初始化这两个术语是相同的。他们不一样。对吗?
【解决方案3】:

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

new std::vector<std::string>{"once", "upon", "a", "time"}; // 4 string elements

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2011-01-02
    • 1970-01-01
    • 2018-05-07
    • 1970-01-01
    • 1970-01-01
    • 2011-09-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多