简体   繁体   English

如何确保std :: call_once真的只调用一次

[英]How to ensure std::call_once really is only called once

Some code I'm working with uses std::call_once so that some initialization only occurs once. 我正在使用的一些代码使用std :: call_once,因此一些初始化只发生一次。 However, there are global objects with constructors that can end up calling the initialization code. 但是,有些构造函数的全局对象最终可能会调用初始化代码。

In the following sample, call_once actually gets called twice. 在下面的示例中,call_once实际上被调用了两次。 I guess it's because the once_flag constructor hasn't ran before it gets used. 我想这是因为once_flag构造函数在使用之前没有运行过。 Is there a way around this so that some initialization code only gets called once without having to prohibit globals? 有没有办法解决这个问题,以便一些初始化代码只被调用一次而不必禁止全局变量?

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

Output is: 输出是:

hello
hello

According to the specs, once_flag should have a trivial constexpr constructor (for example see here - http://en.cppreference.com/w/cpp/thread/once_flag ). 根据规范, once_flag应该有一个简单的constexpr构造函数(例如见这里 - http://en.cppreference.com/w/cpp/thread/once_flag )。 With this in place, if it is global/static, it is not actually "constructed" (no actual function is executed), but more like "value initialized" - like any global/static POD type. 有了它,如果它是全局/静态的,它实际上不是“构造的”(没有执行实际的函数),而更像是“值初始化” - 就像任何全局/静态POD类型一样。 In that case it is not possible to have any constructor run "before" this once_flag is properly initialized. 在这种情况下,不可能在“before”之前运行任何构造函数,这个once_flag被正确初始化。 Given your comment about using MSVC, I guess it can be a bug in the implementation... 鉴于您对使用MSVC的评论,我想这可能是实施中的一个错误......

EDIT: According to the comment below, constexpr is not supported on MSVC at all, so your options are really limited in here... If you have everything in one file, just put your once_flag "above" everything that uses it - the constructors in a file are executed in the order of declaration of objects. 编辑:根据下面的评论,在MSVC上根本不支持constexpr ,所以你的选项在这里真的有限......如果你把所有东西放在一个文件中,只需把你的once_flag “置于”使用它的所有东西 - 构造函数在文件中按对象声明的顺序执行。 If you have the users spread across different files, your only option is to use a function that provides access to static internal once_flag - like in this answer http://www.parashift.com/c++-faq/static-init-order-on-first-use.html . 如果您的用户分布在不同的文件中,您唯一的选择就是使用一个提供静态内部once_flag访问权限的函数 - 就像在这个答案中一样http://www.parashift.com/c++-faq/static-init-order- on-first-use.html

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM