初始化std :: atomic_bool?

Sap*_*apd 39 c++ atomic c++11 visual-studio-2012

我想使用std::atomic_bool因为我想要一个布尔值,它应该被不同的线程访问.

它是一个static成员变量.问题是我想用false第一个状态初始化它.通常我会这样做: std::atomic_bool World::mStopEvent = false;

但问题似乎是它不false作为构造函数.那么我应该如何初始化这样一个变量呢?我正在使用VS 2012.

use*_*116 38

这是Visual Studio 2012中的一个已知问题(称为VC11),您应该对现有的Connect项进行投票,以便Microsoft知道它会影响更多人,因为他们已推迟修复.

嗨,

感谢您报告此错误.我是微软STL的维护者,我想告诉你,虽然这个bug在我们的数据库中仍然有效,但它不会在VC11 RTM(VS 2012 RTM)中修复.所有错误对我们都很重要,但有些错误比其他错误更严重,并且成为我们优先级队列的首要任务.

我在所有STL的活动Connect错误中复制并粘贴此响应,但以下简洁注释专门适用于您的错误:

  • 是的,我们缺少对这些构造atomic_bool,atomic_int等等(atomic<bool>,atomic<int>,等有他们).29.5 [atomics.types.generic]/7说"应该有与原子的整数特化相对应的命名类型,如表145所示,以及atomic_bool对应于指定的atomic<bool>命名类型.每个命名类型都是typedef相应的专业化或者是相应专业化的基类.如果是基类,它应该支持与相应专业化相同的成员函数." 这让我真的想要使用typedef(1种类型总是比2种类型简单),但我需要看看是否会引入任何其他问题.

我不能保证什么时候我们能够解决这个错误,但我们希望尽快这样做(当发生这种情况时我会发送另一个回复) - 我们的第一个机会将是"带外" Herb Sutter在2012年GoingNative会议上宣布了VC11和VC12之间的发布.

注意:Connect不会通知我有关评论的信息.如果您还有其他问题,请给我发电子邮件.

Stephan T. Lavavej高级开发人员 - Visual C++ Libraries stl@microsoft.com

基本上,你std::atomic<T>现在需要使用.


and*_*wrk 23

试试这个:

atomic_bool my_bool = ATOMIC_VAR_INIT(false);
Run Code Online (Sandbox Code Playgroud)

http://en.cppreference.com/w/cpp/atomic/ATOMIC_VAR_INIT

  • 我认为这是最好的答案,因为它以最短的方式解决了问题,并且没有开销。同样,该解决方案是跨平台的,我在VS和Xcode中进行了编译。 (3认同)
  • 是的,在 Mac OS X 上用 Clang 编译,但警告“标量初始值设定项周围的括号 [-Wbraced-scalar-init]”。当然,如果你启用了它。 (2认同)

And*_*owl 20

问题:

您不能使用复制初始化,因为std::atomic_bool它不是可复制构造的:

std::atomic_bool World::mStopEvent = false; // ERROR!
Run Code Online (Sandbox Code Playgroud)

实际上,上述内容相当于:

std::atomic_bool World::mStopEvent = std::atomic_bool(false); // ERROR!
Run Code Online (Sandbox Code Playgroud)

但是,您可以使用直接初始化:

std::atomic_bool World::mStopEvent(false);
Run Code Online (Sandbox Code Playgroud)

根据您的意愿,您可以选择使用大括号而不是括号:

std::atomic_bool World::mStopEvent{false};
Run Code Online (Sandbox Code Playgroud)

BUG:

虽然复制初始化是非法的,无论您选择哪种编译器,VC11附带的标准库的实现似乎都有一个不允许您执行直接初始化的错误.

那么我应该如何初始化这样一个变量呢?

解决方法:

作为一种可能的解决方法,您可以提供一对静态getter/setter包装器 - 分别 - 设置并返回原子布尔标志的值,但在确保它至少初始化一次且不超过一次之前不会.以线程安全的方式获得所需的初始值(您可以考虑这种延迟初始化):

#include <atomic>
#include <mutex>

struct World
{
    static bool is_stop_event_set()
    {
        std::call_once(mStopEventInitFlag, [] () { mStopEvent = false; });
        return mStopEvent;
    }

    static void set_stop_event(bool value)
    {
        std::call_once(mStopEventInitFlag, [value] () { mStopEvent = value; });
        mStopEvent = value;
    }

    static std::atomic_bool mStopEvent;
    static std::once_flag mStopEventInitFlag;
};

std::atomic_bool World::mStopEvent;
std::once_flag World::mStopEventInitFlag;
Run Code Online (Sandbox Code Playgroud)

现在不是mStopEvent直接访问,而是通过is_stop_event_set()函数读取其值:

#include <iostream>

int main()
{
    std::cout << World::is_stop_event_set(); // Will return false
}
Run Code Online (Sandbox Code Playgroud)