C++:同时避免静态初始化顺序问题和竞争条件

Dav*_*ave 4 c++ winapi

我正在使用Windows XP/Visual C++ 2008.

我遇到了一个C++静态初始化顺序问题,我已经用众所周知的"首次使用的构造"成语解决了这个问题:

Foo foo; // Forget this

Foo &foo() // Do this instead
{
   // Use ptr, not reference, to avoid destruction order problems
   static Foo *ptr = new Foo();
   return *ptr;
}
Run Code Online (Sandbox Code Playgroud)

但是,我一直在搜索,看起来Windows(我的平台)并不保证本地静态的线程安全,尽管它确实为全局静态提供了保证.

所以,如果我使我的对象全局化,我得到线程安全但我有初始化顺序问题.如果我使用"首次使用时构造",我会避免初始化顺序问题,但我会遇到竞争条件.我怎样才能同时解决这两个问题?

Die*_*ühl 7

在C++ 2011中,您使用std::call_once():

#include <mutex>
void initialize(Foo*& ptr)
{
    ptr = new Foo();
}
std::once_flag flag
Foo& foo()
{
    static Foo* ptr(0);
    std::call_once(flag, initialize, std::ref(ptr));
    return *ptr;
}
Run Code Online (Sandbox Code Playgroud)

如果您不能使用C++ 2011,您可能希望查看系统的基础设施.对于POSIX,这将是pthread_once().如何在其他平台上完成我不知道的事情.

也就是说,我建议不要使用它,因为它本质上是某种形式的全局数据,并且通常没有充分的理由使用它.有例外,但很少见.实际上非常罕见.

  • 哇,不知道`call_once`.+1 (2认同)