我正在使用Visual Studio 2013,它尚未實現「魔術靜態」功能,因此本地靜態變量初始化不是但線程安全。所以,與其使用本地靜態std :: once_flag和本地靜態指針的線程安全初始化靜態變量
Foo& GetInstance()
{
static Foo foo;
return foo;
}
我做這樣的事情:
std::unique_ptr<Foo> gp_foo;
std::once_flag g_flag;
Foo& GetInstance()
{
std::call_once(g_flag, [](){ gp_foo = std::make_unique<Foo>(); });
return *gp_foo;
}
,但我不喜歡gp_foo
和g_flag
全局變量(第一,問題的靜態初始化的秩序觀念在不同的翻譯單元變量;第二,我想初始化變量,只有當我們需要他們,第一次調用的GetInstance())後,即,所以我採取了以下:
Foo& GetInstance()
{
// I replaced a smart pointer
// with a raw one just to be more "safe"
// not sure such replacing is really needed
static Foo *p_foo = nullptr;
static std::once_flag flag;
std::call_once(flag, [](){ p_foo = new Foo; });
return *p_foo;
}
它似乎工作(至少它通過了測試),但我不確定它是線程安全的,因爲在這裏我們有與多個線程中的靜態局部變量p_foo
和flag
的初始化相同的潛在問題。使用nullptr
初始化原始指針並初始化std::once_flag
似乎比調用Foo
的構造函數更無害,但我想知道它是否非常安全。
那麼,最後一段代碼有什麼問題嗎?
HTTPS://codereview.stackexchange。 com/ – Blacktempel
請參閱[call_once on cppreference](http://en.cppreference.com/w/cpp/thread/call_once);特別是第2點。 – Simple
@Simple _在上述所選函數的執行成功完成之前,組中的所有調用都沒有返回,也就是說,不會通過exception._退出,但我的擔憂與std :: call_once,而是關於這兩行:'static Foo * p_foo = nullptr; std :: once_flag標誌;' – undermind