Visual Studio 2012中的C ++ 11 Magic Statics变通方法

时间:2017-12-06 06:54:50

标签: c++ visual-studio c++11 visual-studio-2012 initialization

我将一些对象定义为全局,这意味着它们的构造函数在程序启动之前或在DllMain()之下输入。这会导致一些问题,这就是我想将它们移动到本地静态的原因。

我们的主要项目主要在Visual Studio 2012下。根据这些帖子。

Magic Statics未在Visual Studio 2012中实现(直到VS 2015)。因此,本地静态变量初始化不会自动受到编译器的并发访问保护。

针对此案例的合适解决方法或解决方案是什么?

以下是我的尝试:

添加锁以保护。但是如果在输入函数之前初始化变量,我的锁可能没用......

// data object
struct Cat
{
    Cat()
    {
        std::cout << __FUNCTION__ <<  "\n";
    }
};

// lock mutex for singleton getter
static std::mutex getcat_m;

// singleton getter
Cat& GetCat(){
    std::cout << __FUNCTION__ <<  " In\n";

    std::lock_guard<std::mutex> lk(getcat_m);
    static Cat cat;

    std::cout << __FUNCTION__ <<  " Out\n";
    return cat;
}

int main(int argc, char* argv[])
{
    std::cout << __FUNCTION__ <<  " In\n";
    Cat& cat = GetCat();
    std::cout << __FUNCTION__ <<  " Out\n";

    std::cin.ignore();
    return 0;
}

它实际上显示了预期。输入函数后调用构造函数。

main In
GetCat In
Cat::Cat
GetCat Out
main Out

但我不确定这是否是一个合适的解决方案。

1 个答案:

答案 0 :(得分:0)

感谢A. A对评论链接18.2.4 Use std::call_once rather than the Double-Checked Locking pattern的评论。

我引用了Guildline中的示例,并重写了我的单例getter代码,如下所示。

// Cat.cpp
static std::once_flag once_Cat;
static Cat* gpCat = nullptr;
void init_Cat() { gpCat = new Cat(); }

Cat& GetCat() {
    std::call_once(once_Cat, init_Cat);
    return *gpCat;
}