原子向量的初始化


12

考虑:

void foo() {
  std::vector<std::atomic<int>> foo(10);
  ...
}

foo的内容现在有效吗?还是我需要显式循环并初始化它们?我检查了Godbolt,它看起来还不错,但是在这一点上,该标准似乎很混乱。

所述的std ::矢量构造器表示,它插入默认插入的实例std::atomic<int>,这是初始化值经由放置new

我认为这种价值初始化的效果适用:

2)如果T是具有默认构造函数的类类型,该构造函数既不是用户提供也不是未删除的(也就是说,它可能是带有隐式定义或默认默认构造函数的类),则将该对象初始化为零,然后将其如果具有非平凡的默认构造函数,则默认初始化;

因此在我看来,原子是零初始化的。所以问题是,是否std::atomic<int>在有效对象中对结果进行零初始化?

我猜答案是“在实践中是,但没有真正定义”?

注意:此答案同意它是零初始化的,但是并没有真正说明是否意味着该对象有效。

Answers:


7

你是正确的担心。按照标准,原子具有默认的构造函数,但是尚未对其进行初始化。这是因为默认构造函数不会初始化atomic:

default-initialized std::atomic<T>不包含T对象,并且它的唯一有效用法是std :: atomic_init的销毁和初始化。

这在某种程度上违反了正常的语言规则,并且某些实现仍然会初始化(如您所指出的)。

话虽这么说,我建议您采取额外的步骤以确保100%正确地根据标准对其进行了初始化-毕竟,您正在处理并发性问题,在这些问题中,很难跟踪错误。

有很多方法可以避免此问题,包括使用包装器:

struct int_atomic {
   std::atomic<int> atomic_{0};//use 'initializing' constructor
};

还是实际使用atomic_init。无论如何,您已经已经必须在问题中的代码之间进行同步了
轨道上的Lightness Races,

默认构造函数是微不足道的,因此无论如何都不会被调用(按问题中的引号)
Lightness Races in Orbit

@LightnessRaceswithMonica这也是可能的,我只想强调包装器
darune

@LightnessRaceswithMonica这是正常语言规则的例外-即使某些编译器未实现此例外。我不确定StoreTeller的答案是否100%准确。
darune

2

即使调用了默认构造函数(它也不是因为它很简单),它实际上也不会做任何事情

零初始化显然不能保证产生有效的原子。只有偶然通过零初始化其所有成员来创建有效原子时,这才起作用。

而且,由于原子不可复制,因此您不能在向量构造函数中提供初始化值。

现在,您应该遍历容器和std::atomic_init每个元素。如果您需要对此进行锁定,那很好,因为您出于相同的原因已经在同步矢量的创建。


@darune我认为这是一种同步;)
Lightness Races in Orbit
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.