【问题标题】:Aggregate initialization vs uniform initialization聚合初始化与统一初始化
【发布时间】:2020-03-18 11:55:07
【问题描述】:

我对 C++11 统一初始化的了解越多,我就越困惑。 Scott Meyers 在 Effective Modern C++(第 55 页)中说声明

Widget w2{};

总是调用默认构造函数(即使存在带有std::initializer_list 参数的构造函数)。

乍一看,这似乎与 Stroustrup 的书《C++ 编程语言》第 4 版一致,例如根据第1200页的表格声明

std::atomic<T> x;

保持原子变量未初始化,而

std::atomic<T> x {};

调用“默认构造函数”,使 x 代表一个值初始化的 T 对象。

但是,我不敢相信std::atomic&lt;T&gt; x; 不再调用 C++11 中的默认构造函数,所以我在这里完全糊涂了。

最后,在看了 C++11 标准(n3337 草案)之后,我的困惑就更大了。 在第 1102 页,我们有:

template <> struct atomic<integral > {
  //[...] list of non-constructor functions
  atomic() noexcept = default;
  constexpr atomic(integral ) noexcept;
  atomic(const atomic&) = delete;
  //[...] other non-constructor functions
};

在第 1104 页(第 29.5.5 点)我们看到

原子积分特化和特化 atomic 应具有标准布局。他们每个人都有一个 平凡的默认构造函数和平凡的析构函数。他们每一个 支持聚合初始化语法。

那么具有用户定义构造函数的类现在支持聚合初始化? 是不是因为构造函数是constexpr

当我们写的时候会发生什么

std::atomic<T> x {};

这是聚合初始化吗?还是调用(微不足道的)默认构造函数?

【问题讨论】:

  • 不要阅读草稿并从那里得出结论,在阅读标准之后......草稿是在其他东西标准化之前编写的,因此它们会在其中混淆一些东西,一些草稿取决于关于其他人首先实施,但大多数是在不了解或不依赖其他提案的情况下编写的......
  • 这个版本的草案(据称)几乎与官方 C++11 标准相同。

标签: c++


【解决方案1】:

那么具有用户定义构造函数的类现在支持聚合初始化?

只有聚合支持聚合初始化。只有当构造函数被定义为默认或删除时,聚合才能具有用户定义的构造函数。

这将在 C++20 中发生变化,完全不允许用户声明的构造函数。

这是因为构造函数是 consexpr 吗?

constexpr对此没有影响。

std::atomic<T> x {};

这是聚合初始化吗?

这是列表初始化。如果类型是聚合,则列表初始化将聚合初始化对象。 std::atomic 不是聚合,因为它有一个用户提供的既不默认也不删除的构造函数:

constexpr atomic( T desired ) noexcept; // (2) (since C++11)

对于std::atomic,此列表初始化规则适用:

  • 否则,如果初始化器列表没有元素并且 T 是具有默认构造函数的类类型,则该对象为值初始化

值初始化会调用此类的默认构造函数。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-23
    • 2017-07-01
    • 1970-01-01
    • 2019-07-30
    相关资源
    最近更新 更多