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;
}