我对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 {};
这是聚合初始化吗?还是调用(简单的)默认构造函数?
答案 0 :(得分:4)
具有用户定义的构造函数的类现在支持聚合初始化吗?
仅聚合支持聚合初始化。仅当构造函数定义为默认或删除时,聚合才可以具有用户定义的构造函数。
这将在C ++ 20中发生变化,在该版本中根本不允许用户声明构造函数。
是因为构造函数是consexpr吗?
constexpr
对此没有影响。
std::atomic<T> x {};
这是聚合初始化吗?
这是列表初始化。如果类型是聚合,则列表初始化将聚合初始化对象。 std::atomic
不是集合,因为它具有用户提供的构造函数,该构造函数既未默认也未删除:
constexpr atomic( T desired ) noexcept; // (2) (since C++11)
对于std::atomic
,适用以下列表初始化规则:
- 否则,如果初始化列表中没有元素,并且T是具有默认构造函数的类类型,则该对象将值初始化。
值初始化会调用此类的默认构造函数。