C++ std::原子_标志作为成员变量

C++ std::原子_标志作为成员变量,c++,c++11,C++,C++11,在类构造函数中初始化std::atomic_标志的安全方法是什么 似乎在问与我相同的问题-除了这里询问者抱怨编译器问题 我的问题与C++标准本身有关。根据,未指定使用构造函数初始值设定项语法初始化std::atomic_标志 std::atomic_flag static_flag = ATOMIC_FLAG_INIT; // static initialization, // guaranteed to be available during dynamic initialization of

在类构造函数中初始化
std::atomic_标志
的安全方法是什么

似乎在问与我相同的问题-除了这里询问者抱怨编译器问题

我的问题与C++标准本身有关。根据,未指定使用构造函数初始值设定项语法初始化
std::atomic_标志

std::atomic_flag static_flag = ATOMIC_FLAG_INIT; // static initialization,
// guaranteed to be available during dynamic initialization of static objects.

int main()
{
    std::atomic_flag automatic_flag = ATOMIC_FLAG_INIT; // guaranteed to work
//    std::atomic_flag another_flag(ATOMIC_FLAG_INIT); // unspecified
}
这个信息正确吗?如果是,我假设:

struct Foo
{
  Foo() : flag(ATOMIC_FLAG_INIT)
  { }

  std::atomic_flag flag;
};

…也未指明。那么,这是否意味着我们不能将
std::atomic_标志
用作类的成员变量?或者,如果我们在类构造函数中简单地调用
std::atomic_flag::clear()
,安全吗?

C++11标准(好的,)对
atomic_flag_INIT的定义是

7.17.8原子标志类型和操作

ATOMIC_FLAG_INIT
可用于将
ATOMIC_FLAG
初始化为 清除状态。未使用显式初始化的
原子\u标志
ATOMIC_FLAG_INIT
最初处于不确定状态

范例

   atomic_flag guard = ATOMIC_FLAG_INIT;

C++标准使用单词初始化来概括变量可以被赋予初始值的所有方式。由于没有进一步的相反措辞,我理解的意图是,

atomic\u flag guard(atomic\u flag\u INIT)
,以及在构造函数初始值设定项列表中使用
atomic\u flag\u INIT
,也是有效的,且未指定。我认为你引用的站点对单个示例的理解太多了。本标准中的示例不是规范性的,尤其是,示例显示了一种做某事的方法并不意味着这是唯一可以接受的方法。

自N3337到N3936(当前的C++14草案)以来,有关使用原子标志的措辞发生了变化。前者在复制初始化上下文中显示了示例中
ATOMIC\u FLAG\u INIT
宏的可能用法,这些用法是非规范性的,并且没有提及其他初始化上下文中的用法

N3936澄清了用法,不再将复制初始化用法作为示例列出,而是作为说明本身的一部分列出

§29.7/4[原子标志]

原子\u标志\u INIT
的定义应确保其可用于 将
原子_标志
类型的对象初始化为清除状态。宏可用于 表格:

 atomic_flag guard = ATOMIC_FLAG_INIT;
未指定宏是否可用于其他初始化上下文。对于一个完整的静态持续时间对象,该初始化应该是静态的。除非使用
ATOMIC\u FLAG\u INIT
初始化,否则未指定
ATOMIC\u FLAG
对象的初始状态是set还是clear

讨论了这些变化的基本原理

因此,在成员初始值设定项列表中使用宏是不可靠的。解决方案是使用非静态数据成员初始值设定项或大括号或等效初始值设定项来初始化
原子_标志
。然后,它将在副本初始化上下文中初始化

struct Foo
{
  std::atomic_flag flag = ATOMIC_FLAG_INIT;
};

FWIW,它不再是N3936中的示例,而是描述的一部分。它甚至还添加了以下语句-未指定宏是否可以在其他初始化上下文中使用。因此,即使您的答案对于C++11标准是正确的,使用直接初始化也有可能在以后不起作用。@Praetorian Ick,他们为什么这样做?一些挖掘发现了促使更改的缺陷报告。请参阅我刚才发布的答案。MSVC++给出
错误C2797:成员初始值设定项列表中的列表初始化或未实现非静态数据成员初始值设定项。
用于您的代码示例。@Serge您使用的是VS2013吗?它有一个用大括号或同等初始值设定的棋盘格历史。他们最初支持它,但是实现中的错误太多了,更新4(我认为)完全取消了对该特性的支持。上面的代码在VS2015上编译。