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

Mik*_*eMB 5 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);
Run Code Online (Sandbox Code Playgroud)

不仅不能保证,而且实际上是未定义的行为。

如果是这样的话,那么恕我直言,这是使用原子的一个主要陷阱,特别是因为它似乎是在大多数平台上“按预期”工作的 UB 案例之一:https: //godbolt.org/g/二甲基乙二醇二乙醚

编辑:我也不太明白,为什么这“确保与 C 的兼容性”仅仅保证所有位都设置为零会有什么危害?

注意: 我知道我可以写std::atomic<int> a{0}

YSC*_*YSC 1

是的,std::atomic<int> a{};初始化a为零。

\n\n

此语法启动的值初始化std::atomic<int>,进而运行零初始化1。这意味着,即使std::atomic<int>有一个默认构造函数2,它也不会被称为3并且 的所有成员都a被零初始化。

\n\n
\n\n

1)

\n\n
\n

[dcl.init]/8.2

\n\n

8) 对类型的对象进行值初始化T意味着:

\n\n

8.2) 如果T是一个(可能是 cv 限定的)类类型,没有用户提供或删除的默认构造函数,则该对象被零初始化,并且检查默认初始化的语义约束,并且 ifT有一个不平凡的默认构造函数,该对象是默认初始化的;

\n
\n\n

2)

\n\n
\n

[atomics.types.operations]/2

\n\n
 atomic() noexcept = default;\n
Run Code Online (Sandbox Code Playgroud)\n\n

效果:使原子对象处于未初始化状态。[\xe2\x80\x89注意:这些语义确保与 C 的兼容性。\xe2\x80\x94\xe2\x80\x89end note\xe2\x80\x89]

\n
\n\n

3)

\n\n
\n

[dcl.fct.def.default]/5

\n\n

如果函数是用户声明的并且在第一次声明时未显式默认或删除,则该函数是用户提供的。

\n
\n