【问题标题】:c++ singleton implementation Meyer's vs call_oncec++单例实现Meyer's vs call_once
【发布时间】:2020-02-08 16:19:58
【问题描述】:

嗯,我在自己的项目中使用单例。最常用的单例实现可能是 Meyer 的单例以及使用 std::call_once 或 pthread_once 的单例。对于并行计算,它们都是线程安全的

//Meyer's singleton
class MySingleton{
public:
  static MySingleton& getInstance(){
    static MySingleton instance;
    // volatile int dummy{};
    return instance;
  }
private:
  MySingleton()= default;
  ~MySingleton()= default;
  MySingleton(const MySingleton&)= delete;
  MySingleton& operator=(const MySingleton&)= delete;

};


//with call_once
class MySingleton{
public:
  static MySingleton& getInstance(){
    std::call_once(initInstanceFlag, &MySingleton::initSingleton);
    // volatile int dummy{};
    return *instance;
  }
private:
  MySingleton()= default;
  ~MySingleton()= default;
  MySingleton(const MySingleton&)= delete;
  MySingleton& operator=(const MySingleton&)= delete;

  static MySingleton* instance;
  static std::once_flag initInstanceFlag;

  static void initSingleton(){
    instance= new MySingleton;
  }
};

MySingleton* MySingleton::instance= nullptr;
std::once_flag MySingleton::initInstanceFlag;

Meyer 的实现使用局部静态变量来确保线程安全并返回实例标识,而后者通过 call_once 实现并返回指针。在我的实验中,Meyer 的实现速度更快一些。但是大多数项目使用 call_once 方法进行最基本的单例实现,尽管项目的一些小组件使用了 Meyer 的实现。我只是想知道有什么原则可以遵循,这两种不同的实施方式的优缺点是什么?

【问题讨论】:

  • 恕我直言,基本上,两个实现是相同的。 Meyer 的实现要优雅一些。例如,在这种情况下,第二个实现有一个不必要的 initSingleton 方法。但是,如果初始化会更复杂,这个方法也很有用。
  • Meyer 的实现对“Destruction Order Fiasco”是明智的,见DOF,而第二个是内存泄漏明智......
  • Meyer 唯一的破坏顺序风险是,如果您的破坏依赖于不是“正确”单例的静态对象,例如 std::cout 和 std::cin。第二种方法不提供在析构函数中清理代码的机会。

标签: c++ parallel-processing singleton


【解决方案1】:

call_once 版本保留一个指向实例的指针,并使用new 创建它。由于从未在指针上调用过delete,因此如果需要在实例析构函数中运行合理的代码,此解决方案会带来一些麻烦。除了进程退出时烦人的悬空指针之外,如果实例析构函数只是您的示例中的默认析构函数,则可以考虑使用它。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-06-11
    • 2019-07-20
    • 1970-01-01
    • 1970-01-01
    • 2011-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多