【发布时间】:2018-03-21 08:00:18
【问题描述】:
这里的 work 是指std::atomic<T> a{} 有效地零初始化a。我一直这么想,并且一直在实际使用它,直到this。在解释我对此的理解之前,我想表明,至少 gcc 和 clang 在实践中是这样做的。
#include <cstring>
#include <atomic>
#include <iostream>
int main() {
using atomic = std::atomic<int>;
auto p = (atomic*)operator new(sizeof(atomic));
std::memset(p, -1, sizeof(atomic));
new(p) atomic{};
std::cout << p->load() << std::endl;
}
以下是我对为什么会起作用的解释(当然,您可能会不这么认为)。标准是这样说的
在以下操作定义中:
- A 指的是一种原子类型。
[...]
A::A() noexcept = default;效果:使原子对象处于未初始化状态。 [注意:这些语义确保了与 C 的兼容性。- 尾注]
它基本上说默认构造函数是微不足道的,什么都不做。我对此表示同意,但我不明白这如何使值初始化不适用。根据cppref,值初始化的影响包括(强调我的):
如果 T 是一个类类型,其默认构造函数既不是 用户提供或删除(也就是说,它可能是一个类 隐式定义或默认的默认构造函数),对象是 零初始化,然后默认初始化,如果它有 非平凡的默认构造函数;
std::atomic有一个默认的默认构造函数,所以对象是
- 零初始化然后
- 如果它有一个非平凡的默认构造函数,它是默认初始化的。
第 2 点在这里不适用,因为默认的默认构造函数是微不足道的,但我没有看到任何使第 1 点无效的语句。我的理解是正确的还是我遗漏了什么?
【问题讨论】:
-
在您链接到的问题中,原子变量未显式初始化,因此使用默认构造函数。它什么也不做。但是你显式地初始化你的变量,调用你描述的值初始化机制,所以你很好。
-
所有带有新位置等的东西都只是分散注意力。
-
好吧,你让我去验证我在 cmets 中对另一篇文章所做的假设。所以我为此道歉。你是对的。
-
@Cheersandhth.-Alf 需要放置 new 来表明零确实是值初始化的结果,而不是碰巧存在一些垃圾值。
-
问题是在当前措辞下的
std::atomic<T>不需要包含T。您可以将atomic中的字节归零,但这不足以解释它所指的T值。这显然是一种次优状态。有一篇论文可以改变这一点。
标签: c++ c++11 language-lawyer atomic value-initialization