11

once_flag应该初始化什么?我试过falseand 0,两者都给出了类似于下面的错误(下面是0):

no viable conversion from 'int' to 'std::once_flag'

这是我尝试使用它的方式。(我认为即使语言初始化它们也不初始化静态是不好的风格,所以我真的更喜欢在那里有一些东西)。

MyClass& GetMyClass()
{
    static std::once_flag flag;
    static MyClass cls;

    std::call_once(flag, []() {
        // Initialize class
    });

    return cls;
}
4

4 回答 4

11

更新

如果我们查看草案 C++ 标准部分30.4.4.1 Struct once_flag我们可以看到构造函数定义为:

constexpr once_flag() noexcept;

因为它是一个constexpr ,所以您的静态实例将被静态初始化,我们可以在30.4.4.2 Function call_once部分中看到一个使用静态实例的示例:

void g() {
 static std::once_flag flag2;
 std::call_once(flag2, initializer());
}

原来的

如果我们查看std::once_flag的文档,它会说:

once_flag();

Cnstructs an once_flag object. The internal state is set to indicate that no function
has been called yet. 

如果我们进一步查看call_once的文档文档,我们会看到以下示例,该示例演示了如何使用std::once_flag

#include <iostream>
#include <thread>
#include <mutex>

std::once_flag flag; 

void do_once()
{
    std::call_once(flag, [](){ std::cout << "Called once" << std::endl; });
}

int main()
{
    std::thread t1(do_once);
    std::thread t2(do_once);
    std::thread t3(do_once);
    std::thread t4(do_once);

    t1.join();
    t2.join();
    t3.join();
    t4.join();
}

具有以下预期输出:

Called once
于 2013-11-15T02:58:58.263 回答
3

由于您的问题已在其他地方得到解答,作为您发布的代码的替代方案,您也可以这样做:

// private function in anonymous namespace or something
MyClass& initMyClass() {
    static MyClass c;
    /* initialize c */
    return c;
}

然后让客户打电话

MyClass& GetMyClass() {
    static MyClass& c = initMyClass();
    return c;
}

因为静态初始化现在在 C++11 中是线程安全的。然后你就不必乱七八糟了call_once

于 2013-11-15T03:37:26.350 回答
2

你想做什么?您不能std::once_flag使用任何值进行初始化,因为它只有一个不带任何参数的构造函数。

http://en.cppreference.com/w/cpp/thread/once_flag

一次标志();构造一个 once_flag 对象。内部状态设置为指示尚未调用任何函数。

顺便说一句,您认为不初始化静态变量是一种不好的风格的原因是什么?

于 2013-11-15T02:59:05.137 回答
1

ONCE_FLAG_INIT

编辑:仅限 C,而不是 C++。中定义<threads.h>

于 2013-11-15T03:00:23.533 回答