列表初始化是否将原子初始化为零?

时间:2018-07-30 16:36:19

标签: c++ initialization atomic

问题:

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}

1 个答案:

答案 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

     

如果函数是由用户声明的,并且未在其第一个声明中明确地默认或删除,则由用户提供。