如何确保std :: call_once实际上仅被调用一次 [英] How to ensure std::call_once really is only called once

查看:162
本文介绍了如何确保std :: call_once实际上仅被调用一次的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用的某些代码使用std :: call_once,因此某些初始化仅发生一次。但是,有些全局对象的构造函数最终可能会调用初始化代码。

Some code I'm working with uses std::call_once so that some initialization only occurs once. However, there are global objects with constructors that can end up calling the initialization code.

在以下示例中,call_once实际上被调用了两次。我猜这是因为after_flag构造函数在使用之前尚未运行。有没有办法避免某些初始化代码只被调用一次而不必禁止全局变量?

In the following sample, call_once actually gets called twice. I guess it's because the once_flag constructor hasn't ran before it gets used. 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;
}

输出为:

hello
hello


推荐答案

根据规范, once_flag 应该具有琐碎的 constexpr 构造函数(例如,在此处查看- http://en.cppreference.com/w/cpp/thread/once_flag )。使用此功能后,如果它是全局/静态的,则它实际上不是构造的(不执行任何实际功能),而更像是值初始化-像任何全局/静态的POD类型。在这种情况下,不可能在此 once_flag 正确初始化之前之前运行任何构造函数。考虑到您对使用MSVC的评论,我想这可能是实现中的错误...

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 ). 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. In that case it is not possible to have any constructor run "before" this once_flag is properly initialized. Given your comment about using MSVC, I guess it can be a bug in the implementation...

编辑:
根据以下评论,<$ c MSVC根本不支持$ c> constexpr ,因此您的选择在这里确实受到限制...如果将所有内容都保存在一个文件中,只需将 once_flag放入在使用它的所有内容之上-文件中的构造函数按照对象声明的顺序执行。如果您将用户分散在不同的文件中,则唯一的选择是使用提供对静态内部 once_flag 的访问的功能-类似于此答案 http://www.parashift.com/c++-faq/static-init- order-on-first-use.html

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. 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 .

这篇关于如何确保std :: call_once实际上仅被调用一次的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆