我对 C++11 统一初始化了解得越多,我就越困惑。在 Effective Modern C++(第 55 页)中的 Scott Meyers 说,声明
Widget w2{};
Run Code Online (Sandbox Code Playgroud)
始终调用默认构造函数(即使存在带有std::initializer_list参数的构造函数)。
乍一看,这似乎与 Stroustrup 书“C++ 编程语言”的第 4 版一致,例如根据第 1200 页上的表格声明
std::atomic<T> x;
Run Code Online (Sandbox Code Playgroud)
使原子变量未初始化,而
std::atomic<T> x {};
Run Code Online (Sandbox Code Playgroud)
调用“默认构造函数”,以便 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
};
Run Code Online (Sandbox Code Playgroud)
在第 1104 页(第 29.5.5 点)我们看到
原子积分特化和特化原子应有标准布局。它们每个都有一个普通的默认构造函数和一个普通的析构函数。它们都应支持聚合初始化语法。
那么具有用户定义构造函数的类现在支持聚合初始化吗?这是因为构造函数是constexpr?
当我们写作时会发生什么
std::atomic<T> x {};
Run Code Online (Sandbox Code Playgroud)
这是聚合初始化吗?或者调用(平凡的)默认构造函数?
那么具有用户定义构造函数的类现在支持聚合初始化吗?
仅聚合支持聚合初始化。仅当构造函数定义为默认或删除时,聚合才能具有用户定义的构造函数。
这将在 C++20 中发生变化,其中根本不允许用户声明构造函数。
这是因为构造函数是 consexpr 吗?
constexpr对此没有影响。
Run Code Online (Sandbox Code Playgroud)std::atomic<T> x {};这是聚合初始化吗?
这是列表初始化。如果类型是聚合,则列表初始化将聚合初始化对象。std::atomic不是聚合,因为它有一个用户提供的构造函数,既不默认也不删除:
Run Code Online (Sandbox Code Playgroud)constexpr atomic( T desired ) noexcept; // (2) (since C++11)
对于std::atomic,适用此列表初始化规则:
- 否则,如果初始值设定项列表没有元素并且 T 是具有默认构造函数的类类型,则该对象是值初始化的。
并且值初始化会调用此类的默认构造函数。
| 归档时间: |
|
| 查看次数: |
569 次 |
| 最近记录: |