46

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

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

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

4

4 回答 4

41

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

你好,

感谢您报告此错误。我是 Microsoft 的 STL 维护者,我想让你知道,虽然这个错误在我们的数据库中仍然存在,但它不会在 VC11 RTM (VS 2012 RTM) 中得到修复。所有错误对我们都很重要,但有些错误比其他错误更严重,并且上升到我们优先级队列的顶部。

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

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

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

注意:Connect 不会通知我有关评论的信息。如果您有任何进一步的问题,请给我发电子邮件。

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

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

于 2013-04-01T20:13:33.067 回答
31

试试这个:

atomic_bool my_bool = ATOMIC_VAR_INIT(false);

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

于 2015-07-02T09:35:45.413 回答
26

问题:

您不能使用copy-initialization,因为std::atomic_bool它不可复制:

std::atomic_bool World::mStopEvent = false; // ERROR!

其实上面等价于:

std::atomic_bool World::mStopEvent = std::atomic_bool(false); // ERROR!

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

std::atomic_bool World::mStopEvent(false);

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

std::atomic_bool World::mStopEvent{false};

漏洞:

尽管无论您选择哪种编译器,复制初始化都是非法的,但似乎 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;

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

#include <iostream>

int main()
{
    std::cout << World::is_stop_event_set(); // Will return false
}
于 2013-04-01T20:14:34.070 回答
2

怎么样:

std::atomic_bool World::mStopEvent(false);
于 2013-04-01T20:09:39.783 回答