问题:
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}
答案 0 :(得分:1)
是的,std::atomic<int> a{};
将a
初始化为零。
此语法开始std::atomic<int>
的值初始化,后者依次运行零初始化 1 。这意味着,即使std::atomic<int>
具有默认的构造函数 2 ,也不会将其称为 3 ,并且a
的所有成员都将初始化为零。 / p>
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
如果函数是由用户声明的,并且未在其第一个声明中明确地默认或删除,则由用户提供。