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

Does list initialization initialize atomics to zero?

本文关键字:初始化 是否 列表      更新时间:2023-10-16

问题:

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

如果函数是用户声明的,并且在第一次声明时没有显式默认或删除,那么它就是用户提供的。