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

Posted

技术标签:

【中文标题】列表初始化是不是将原子初始化为零?【英文标题】:Does list initialization initialize atomics to zero?列表初始化是否将原子初始化为零? 【发布时间】:2018-07-30 16:36:18 【问题描述】:

问题:

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&lt;int&gt; a0

【问题讨论】:

我认为你是对的,不幸的是,根据标准,值没有被初始化。 【参考方案1】:

是的,std::atomic&lt;int&gt; a;a 初始化为零。

此语法启动std::atomic&lt;int&gt;值初始化,然后运行零初始化1。这意味着,即使std::atomic&lt;int&gt; 有一个默认构造函数2,它也不会被调用3,并且a 的所有成员都是零初始化的。


1)

[dcl.init]/8.2

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

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

2)

[atomics.types.operations]/2

 atomic() noexcept = default;

效果:使原子对象处于未初始化状态。 [ 注意:这些语义确保与 C 的兼容性。— 尾注 ]

3)

[dcl.fct.def.default]/5

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

【讨论】:

不确定我是该喜欢还是讨厌 C++。 实际上,是否可以保证std::atomic&lt;T&gt; 具有T 类型的成员? @MikeMB 这是我问自己的问题,但我现在被困在通勤中。 有这方面的消息吗? @Eric 我认为我的回答完全不正确。我需要回到台式计算机上,重新阅读自 3 年半前我的回答以来发生在 atomic 上的所有内容。

以上是关于列表初始化是不是将原子初始化为零?的主要内容,如果未能解决你的问题,请参考以下文章

全局对象内的内置类型的成员变量是不是已初始化为零?

Windows XP 会自动将数组初始化为零吗?

如何将 List<T> 初始化为给定大小(而不是容量)?

使用 memset 将结构体数组及其成员初始化为零

C++中,类内的成员变量自动初始化为零吗,而全局变量随意赋值

具有 char 数组的 C++ 结构以不寻常的方式初始化为零