C 11魔术静态在Visual Studio 2012中的解决方法



i有一些定义为全局的对象,这意味着在程序启动或下dllmain()下,输入其构造函数。这会导致一些问题,这就是为什么我想将它们移至本地静态。

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

  • 在另一个翻译单元的静态破坏阶段引用时,"魔术静态"单例崩溃了"
  • 支持C 11/14/17功能(现代C )

《魔术静态》在2012年Visual Studio中没有实现(直到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__ <<  " Inn";
    std::lock_guard<std::mutex> lk(getcat_m);
    static Cat cat;
    std::cout << __FUNCTION__ <<  " Outn";
    return cat;
}
int main(int argc, char* argv[])
{
    std::cout << __FUNCTION__ <<  " Inn";
    Cat& cat = GetCat();
    std::cout << __FUNCTION__ <<  " Outn";
    std::cin.ignore();
    return 0;
}

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

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

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

感谢A链接的评论18.2.4使用std :: call_once而不是双重检查的锁定模式。

我从公会中引用了示例,并将我的单例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;
}

最新更新