【问题标题】:Realize a singleton-like functionality using std::call_once使用 std::call_once 实现类似单例的功能
【发布时间】:2018-09-21 11:36:41
【问题描述】:

我想使用 std::call_once 实现一个类似单例的功能,只是为了好玩,或者也许可以改进单例模式本身。这是我到目前为止尝试过的,但我被卡住了。任何帮助将不胜感激。

class single {
public:

private:
    single(){}
    friend void boo(unique_ptr<single>&);
};

void boo(unique_ptr<single>& f) {
    f.reset(new single());
}

unique_ptr<single>& bar() {
    static once_flag flag;
    static unique_ptr<single> f;
    call_once(flag, boo,f);
    return f;
}


int main()
{
    unique_ptr<single> f;
    f = move(bar());

    unique_ptr<single> f2;
    f2 = move(bar()); // this should not work but it does, work-around?
}

【问题讨论】:

  • @FrederikDeRuyck:链接排除了没有 call_once 的答案
  • 当我阅读你的代码时,你第一次调用bar时会返回单音,但是下次调用bar时,bar会返回一个空的unique_ptr,这不常见。
  • @Oliv:是的,你是对的,我尝试在那里使用静态。哇,它至少可以编译。我想将 boo() 隐藏在命名空间中。但是在 main() 中的 move(bar() 之后,bar 中的实例可能有问题
  • 所以现在考虑标准确保静态本地函数(如f)只初始化一次。所以这里有某种形式的代码重复。

标签: c++ singleton std-call-once


【解决方案1】:

static 就够了。 It does thread-safe initialization for you, no need for call_once:

如果多个线程同时尝试初始化同一个静态局部变量,则初始化只发生一次(使用std::call_once 的任意函数可以获得类似的行为)。

注意:此功能的通常实现使用双重检查锁定模式的变体,这将已初始化的本地静态变量的运行时开销减少为单个非原子布尔比较。

因此:

unique_ptr<single>& bar() {
    static unique_ptr<single> f{new single};
    return f;
}

或者更好:

single& bar() {
    static single f;
    return f;
}

【讨论】:

  • 我仍然可以从 main 调用 bar() 两次,任何解决方法。我想用 std::call_once 来实现 Singleton。
  • @ark1974 可以,您可以多次拨打bar。但是,如果您移动该智能指针,它会在后续调用中返回 nullptr。
  • 同意;我仍然想用 std::call_oncce 简化整个模式
  • @ark1974 嗯...,call_once 看起来更像是一个复杂问题,而不是简化。
  • @ark1974 您的问题可以被标记为重复。
猜你喜欢
  • 2020-02-08
  • 2019-02-28
  • 2019-08-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-31
  • 2016-05-10
相关资源
最近更新 更多