2013-04-01 268 views
35

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

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

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

回答

36

这是一个known issue in Visual Studio 2012 (known as VC11),你应该在现有的连接项目让微软知道它会影响更多的人,因为他们已经推迟修复投票。

Hi,

Thanks for reporting this bug. I'm Microsoft's maintainer of the STL, and I wanted to let you know that while this bug remains active in our database, it won't be fixed in VC11 RTM (VS 2012 RTM). All bugs are important to us, but some are more severe than others and rise to the top of our priority queue.

I'm copying-and-pasting this response across all of the STL's active Connect bugs, but the following terse comments apply specifically to your bug:

  • Yep, we're missing these constructors on atomic_bool , atomic_int , etc. (atomic<bool> , atomic<int> , etc. have them). 29.5 [atomics.types.generic]/7 says "There shall be named types corresponding to the integral specializations of atomic, as specified in Table 145, and a named type atomic_bool corresponding to the specified atomic<bool> . Each named type is a either typedef to the corresponding specialization or a base class of the corresponding specialization. If it is a base class, it shall support the same member functions as the corresponding specialization." which makes me really want to use typedefs (1 type is always simpler than 2 types), but I'll need to see if that would introduce any other issues.

I can't promise when we'll be able to resolve this bug, but we hope to do so as soon as possible (and I'll send another response when that happens) - our first opportunity will be the "out of band" release between VC11 and VC12 that Herb Sutter announced at the GoingNative 2012 conference.

Note: Connect doesn't notify me about comments. If you have any further questions, please E-mail me.

Stephan T. Lavavej Senior Developer - Visual C++ Libraries [email protected]

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

2

如何:

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

同样的错误: '错误C2440:初始化:不能从转换' bool'改为'std :: atomic_bool' 1>没有构造函数可以采用源类型,或者构造函数重载解析模糊不清[ – Sapd

20

问题:

不能使用复制初始化,因为std::atomic_bool不是拷贝构造:

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

其实,上面的是等价于:

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

但是,您可以使用direct-initiali矩阵特殊积

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

在你的愿望,你可以选择,而不是使用圆括号的括号:

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

BUG:

虽然副本初始化是非法的,无论是什么编译器,你选择,似乎VC11附带的标准库的实现有一个错误,不会让你执行直接初始化。

So how I am supposed to initialize such a variable?

解决方法:

作为一种可能的解决办法,可以提供一对静态的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 
} 
+0

]是的,直接初始化不起作用:( – Sapd

+1

@Sapd:我试图提供一种解决方法,希望它有帮助 –

+0

是的,谢谢,我想使用访问器。可惜这个开销是需要的。 – Sapd

16

试试这个:

atomic_bool my_bool = ATOMIC_VAR_INIT(false); 

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

+1

我认为这是这里最好的答案,因为它可以以最短的方式解决问题,而且没有开销。此解决方案也是跨平台的,我在VS和Xcode中进行了补充。 – GuidC0DE

+0

是的,在Mac OS X上与Clang一起编译,但警告标记初始化程序[-Wbraced-scalar-init]的括号。当然,如果你启用它。 – dismine