我想使用std::atomic_bool
,因为我希望有一个布尔值,它应该被不同的线程访问。
这是static
成员变量。问题是我想用false
作为第一个状态来初始化它。通常我会这样做:
std::atomic_bool World::mStopEvent = false;
但问题似乎是它不需要false
作为构造函数。那么我应该如何初始化这样一个变量呢?
我正在使用VS 2012。
答案 0 :(得分:37)
这是一个known issue in Visual Studio 2012 (known as 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 ++库 stl@microsoft.com
基本上,您现在需要使用std::atomic<T>
。
答案 1 :(得分:21)
试试这个:
atomic_bool my_bool = ATOMIC_VAR_INIT(false);
答案 2 :(得分:20)
<强>问题:强>
您无法使用复制初始化,因为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};
<强> 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;
现在不是直接访问mStopEvent
,而是通过is_stop_event_set()
函数读取其值:
#include <iostream>
int main()
{
std::cout << World::is_stop_event_set(); // Will return false
}
答案 3 :(得分:2)
怎么样:
std::atomic_bool World::mStopEvent(false);