我正在使用的一些代码使用std :: call_once,因此某些初始化只发生一次。但是,有些构造函数的全局对象最终可以调用初始化代码。
在下面的示例中,call_once实际上被调用了两次。我想这是因为once_flag构造函数在使用之前没有运行过。有没有办法解决这个问题,以便一些初始化代码只被调用一次而不必禁止全局变量?
#include <mutex>
#include <iostream>
using namespace std;
void Init();
class Global
{
public:
Global()
{
Init();
}
};
Global global;
once_flag flag;
void Init()
{
call_once(flag, []{ cout << "hello" << endl; });
}
int main(int argc, char* argv[])
{
Init();
return 0;
}
输出是:
hello
hello
答案 0 :(得分:4)
根据规范,once_flag
应该有一个简单的constexpr
构造函数(例如,请参见此处 - http://en.cppreference.com/w/cpp/thread/once_flag)。有了它,如果它是全局/静态的,它实际上不是“构造的”(没有执行实际的函数),而更像是“值初始化” - 就像任何全局/静态POD类型一样。在这种情况下,不能让“{1}}正确初始化之前”运行任何构造函数。鉴于您对使用MSVC的评论,我想这可能是实施中的一个错误......
编辑:
根据下面的评论,MSVC根本不支持once_flag
,因此您的选项在这里非常有限......如果您将所有内容都放在一个文件中,只需将constexpr
“放在”所有内容之上使用它 - 文件中的构造函数按对象声明的顺序执行。如果您的用户分布在不同的文件中,您唯一的选择就是使用一个提供静态内部once_flag
访问权限的功能 - 就像在这个答案http://www.parashift.com/c++-faq/static-init-order-on-first-use.html中一样。