列表初始化是否将原子初始化为零
Does list initialization initialize atomics to zero?
问题:
std::atomic<int> a{};
是否初始化a
(为零(?
背景:
通常,我希望T a{};
要么给出编译时错误,要么确保a
已初始化并准备好使用。要么是因为T
是一个类似于基本/POD的类型,并且关于聚合/零/值/列表初始化的语言规则导致所有内容都被初始化为零(我不知道具体是什么(,要么是因为调用了默认构造函数,它"通常"会使对象进入可用状态。当然,需要(不仅允许(双重初始化的类存在,但似乎相当罕见——尤其是在标准库中。
然而,std::atomic
构造函数的文档中显示
1(默认构造函数很简单:除了静态和线程本地对象的零初始化之外,不进行任何初始化。std::atomic_init可以用来完成初始化。
[…]
默认初始化的std::atomic不包含T对象,其唯一有效的用途是通过std::atomic_init进行销毁和初始化,请参阅LWG 2334
我读到这个
std::atomic<int> a{};
assert(a.load() == 0);
不仅不能保证,而且实际上是未定义的行为。
如果是这样的话,那么这就是使用原子论的一个主要陷阱,特别是因为它似乎是在大多数平台上"按预期"工作的UB案例之一:https://godbolt.org/g/DmEGDE
编辑:我也不太明白,为什么这"确保与C的兼容性",仅仅保证所有位都设置为零会有什么害处?
注意:我知道我可以写std::atomic<int> a{0}
std::atomic<int> a{};
将a
初始化为零。
此语法启动std::atomic<int>
的值初始化,然后运行零初始化1。这意味着,即使std::atomic<int>
有一个默认的构造函数2,它也不被称为3并且a
的所有成员都被零初始化。
1(
[dcl.init]/8.2
8( 对
T
类型的对象进行值初始化意味着:8.2(如果
T
是一个(可能是cv限定的(类类型,没有用户提供或删除的默认构造函数,则对象被零初始化,并检查默认初始化的语义约束,如果T
具有非平凡的默认构造函数则对象被默认初始化;
2(
[atomics.types.operations]/2
atomic() noexcept = default;
效果:使原子对象处于未初始化状态。[注意:这些语义确保了与C的兼容性--尾注]
3(
[dcl.fct.def.default]/5
如果函数是用户声明的,并且在第一次声明时没有显式默认或删除,那么它就是用户提供的。
- 列表初始化是否将原子初始化为零
- 使用函数声明进行函数指针初始化 - 是否可能
- 值初始化是否适用于原子对象?
- 聚合的值初始化是否使用其成员的默认初始值设定项?
- C 11联合会的空列表初始化 - 是否保证可以初始化工会的全长
- 找出静态初始化是否结束
- 非本地非内联变量的初始化:是否严格在"main()"函数调用之前进行
- 空字符数组的初始化是否有效
- 变量零初始化-是否有未定义的行为
- 0-原子的初始化是否保证将值成员设置为0
- POD 类对象初始化是否需要构造函数
- 在C++中使用类似 c 的初始化或构造函数初始化是否被认为更好
- 类内成员初始化是否删除赋值运算符
- C++11;非静态数据成员初始化是否可以访问其他数据成员
- 列表初始化是否为隐式转换
- 复制列表初始化是否在概念上调用复制 ctor
- 如何测试/验证零初始化是否发生
- C++默认初始化是否保留先前的零初始化
- 使用新结构体进行聚合初始化是否有效
- 检测CRT初始化是否在注入过程中完成