值初始化是否适用于原子对象?
Does value initialization work for atomic objects?
通过这里的工作,我的意思是std::atomic<T> a{}
有效地零初始化a
。我一直这么想,直到现在才实际使用它。在解释我对此的理解之前,我想表明,至少,gcc 和 clang 在实践中正在这样做。
#include <cstring>
#include <atomic>
#include <iostream>
int main() {
using atomic = std::atomic<int>;
auto p = (atomic*)operator new(sizeof(atomic));
std::memset(p, -1, sizeof(atomic));
new(p) atomic{};
std::cout << p->load() << std::endl;
}
输出在 gcc 和叮当声上都0
。
以下是我对为什么这应该起作用的解释(当然,您可能会不这么认为)。该标准说
在以下操作定义中:
- a A 是指原子类型之一。
[...]
A::A() noexcept = default;
效果:使原子对象处于未初始化状态。[ 注意:这些语义可确保与 C 语言兼容。 — 尾注 ]
它基本上说默认构造函数是微不足道的,什么都不做。我对此没意见,但我看不出这如何使值初始化不适用。根据cppref,值初始化的影响包括(强调我的):
如果 T 是具有既不是的默认构造函数的类类型 用户提供或删除的(也就是说,它可能是一个具有 隐式定义或默认的默认构造函数),对象是 零初始化,如果它有一个 非平凡的默认构造函数;
std::atomic
有一个默认的默认构造函数,因此对象是
- 零初始化,然后
- 如果它具有非平凡的默认构造函数,则它是默认初始化的。
第 2 点在这里不适用,因为默认的默认构造函数微不足道,但我没有看到任何使第 1 点无效的语句。我的理解是正确的还是我错过了什么?
最终,值初始化情况的关键在于 [dcl.init]/7,项目符号 1 和 2:
对 T 类型的对象进行值初始化意味着:
- 如果 T 是具有用户提供的构造函数 ([class.ctor]) 的(可能符合 cv 条件的)类类型(子句 [class]),则默认构造函数 对于 T 被调用(如果 T 没有,则初始化格式不正确 可访问的默认构造函数);
- T 是一个(可能符合 cv 条件的)非联合类类型,没有用户提供的构造函数,则对象为零初始化,并且,如果 T 的隐式声明的默认构造函数是不平凡的,即 构造函数被调用。
- 。
应用上述两个项目符号中的哪一个取决于用户提供的 c'tor。我在另一个答案的评论中没有记住的是,当应用于该答案时,= default;
的复杂性。如果我们看一下 [dcl.fct.def.default]/4 中给出的定义(强调我的):
显式默认函数和隐式声明函数是 统称为默认函数,实现应 为它们提供隐式定义([class.ctor] [class.dtor], [class.copy]),这可能意味着将它们定义为已删除。一个特别的 成员函数是用户提供的,如果它是用户声明的,而不是在其第一个声明中显式默认或删除。一个 用户提供的显式默认函数(即显式 默认在其第一个声明之后)定义在以下点 它是显式默认的;如果隐式定义了这样的函数 删除后,程序格式不正确。[ 注意:将函数声明为 在其第一个声明后默认可以提供有效的执行 和简洁的定义,同时启用稳定的二进制接口 不断发展的代码库。— 尾注 ]
我们看到atomic
的默认 c'tor不是用户提供的,因为它被声明为默认值,而不是被声明然后定义为默认值。因此,[dcl.init]/7 的第二个项目符号是适用的,对象初始化为零,然后是(非)调用(微不足道的默认)构造函数,该构造函数不执行任何操作。
- FLTK 2.0构建和演示,适用于VS2019的2011年左右的代码库
- C++17 - 使用自定义分配器的节点提取/重新插入 - 适用于 clang++/libc++,但不适用于 libstd
- "string.h"在构建适用于iOS的qt应用程序中找不到消息
- 适用于 WebView2 旧版本的示例应用程序
- 在 NVIDIA GEFORCE GTX 1050 上下载适用于 Windows 10 的 openCL 1.2
- __attribute__(优化(0))) 是否适用于"recursively"?
- 为什么 std::erase(std::erase_if) 不是适用于<algorithm>任何容器的模板?
- 使用一个参数的模板函数时出错(适用于 2)
- 使用 适用于 Android 和 iOS 的 tf-lite C++ API
- 为什么这适用于 G++ 而不是 CLANG?
- 适用于 macOS 的 Xcode 应用程序。这就是我设置从USB麦克风输入获取音频的方式。一年前工作,现在没有了。为什么
- 适用于 Linux 的 c++ 上的代理脚本
- 为什么我的 SFINAE 表达式不再适用于 GCC 8.2?
- 使输出流式处理运算符适用于 boost::variant<std::vector<int>、int、double 的正确方法是什么>
- 有没有适用于Windows.lib文件的GNU二进制文件描述符(BFD)
- 如何使此函数适用于 100 个对象 (c++)?
- 构建共享对象 - 使用 Ninja 编译适用于 OSX 和 Windows 上的 Ubuntu Crush
- FlatBuffers C++从缓冲区转换为对象,仅适用于root_type(而Java具有所有)
- 关于"distinct addresses"的规则是否适用于 new 创建的对象?
- 多态是否适用于在C中传递的c++对象引用?