聚合初始化 vs 统一初始化

5

我阅读越多关于 C++11 统一初始化的内容,就越感到困惑。 在《Effective Modern C++》(第55页)中,Scott Meyers说:

Widget w2{};

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

乍一看,这似乎与 Stroustrup 的第四版书籍《C++程序设计语言》一致,例如根据第1200页上的表格,该语句

std::atomic<T> x;

这会使原子变量处于未初始化状态,

std::atomic<T> x {};

调用"default constructor"使x表示一个已初始化的T对象的值。

然而,我无法相信在C++11中std::atomic<T> x;不再调用默认构造函数,所以我完全困惑了。

最后,在查看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点)中,我们看到:

原子积分特化和专门化原子应具有标准布局。它们各自都应该有一个平凡的默认构造函数和一个平凡的析构函数。它们各自都支持聚合初始化语法。

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

当我们编写以下内容时会发生什么:

std::atomic<T> x {};

这是聚合初始化吗?还是(平凡的)默认构造函数的调用?


不要从草案中得出结论,阅读标准后再作判断。草案是在其他事物标准化之前编写的,因此其中可能会有令人困惑的内容。一些草案依赖于先实施其他草案,但大多数草案都是在没有对其他提案的知识或依赖情况下编写的。 - xception
这个版本的草案(据说)几乎与官方的C++11标准完全相同。 - Adrian
1个回答

5

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

只有聚合体支持聚合初始化。如果将构造函数定义为默认或删除,则聚合体可以具有用户定义的构造函数。

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

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

constexpr对此没有影响。

std::atomic<T> x {};

Is this the aggregate initialization?

这是列表初始化。如果类型是聚合体,那么列表初始化将聚合初始化该对象。std::atomic 不是聚合体,因为它有一个用户提供的构造函数,既不是默认的也不是已删除的:
constexpr atomic( T desired ) noexcept; // (2) (since C++11)
对于 std::atomic,适用以下列表初始化规则:
  • 否则,如果初始化列表没有元素并且T是具有默认构造函数的类类型,则对象将被值初始化

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


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接