汇总初始化与统一初始化

时间:2019-11-22 11:53:20

标签: c++

我对C ++ 11统一初始化的了解越多,我就越困惑。 《有效的现代C ++》(第55页)中的Scott Meyers说,该语句

Widget w2{};

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

乍一看,这似乎与Stroustrup的第4版“ C ++编程语言”一致,例如根据第1200页上的表进行声明

std::atomic<T> x;

保留未初始化的原子变量,而

std::atomic<T> x {};

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

但是,我不敢相信std::atomic<T> 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点)上看到

  

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

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

写的时候会发生什么

std::atomic<T> x {};

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

1 个答案:

答案 0 :(得分:4)

  

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

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

这将在C ++ 20中发生变化,在该版本中根本不允许用户声明构造函数。

  

是因为构造函数是consexpr吗?

constexpr对此没有影响。

std::atomic<T> x {};
     

这是聚合初始化吗?

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

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

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

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

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