c ++单例实现迈耶的vs call_once

Wei*_*Sun 6 c++ parallel-processing singleton

好吧,我在自己的项目中使用单例。最常用的单例实现可能是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;
Run Code Online (Sandbox Code Playgroud)

Meyer的实现使用局部静态变量来确保线程安全并返回实例标识,而后者则通过call_once实现并获取指针。在我的实验中,Meyer的隐含性更快一些。但是,大多数项目都使用call_once方法来实现最基本的单例实现,尽管使用Meyer实现的项目中的一小部分也是如此。我只是想知道有没有遵循的原则,这两种不同的实现有什么利弊?

p-a*_*l-o 4

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