列表初始化是不是将原子初始化为零?
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<int> a0
【问题讨论】:
我认为你是对的,不幸的是,根据标准,值没有被初始化。 【参考方案1】:是的,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 限定的)类类型,没有用户提供或删除的默认构造函数,则该对象被零初始化并检查默认初始化的语义约束,如果 @ 987654332@ 有一个非平凡的默认构造函数,对象是默认初始化的;
2)
[atomics.types.operations]/2
atomic() noexcept = default;
效果:使原子对象处于未初始化状态。 [ 注意:这些语义确保与 C 的兼容性。— 尾注 ]
3)
[dcl.fct.def.default]/5
如果函数是用户声明的并且在其第一次声明时没有显式默认或删除,则该函数是用户提供的。
【讨论】:
不确定我是该喜欢还是讨厌 C++。 实际上,是否可以保证std::atomic<T>
具有T
类型的成员?
@MikeMB 这是我问自己的问题,但我现在被困在通勤中。
有这方面的消息吗?
@Eric 我认为我的回答完全不正确。我需要回到台式计算机上,重新阅读自 3 年半前我的回答以来发生在 atomic 上的所有内容。以上是关于列表初始化是不是将原子初始化为零?的主要内容,如果未能解决你的问题,请参考以下文章