7

Well, i'm using singleton in my own project. The most frequently used singleton implementation might be Meyer's singletion and that of using std::call_once or pthread_once. Both of them are thread safe for parallelized computing

//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's implimentation using local static variable to ensure thread safety and return the instance identity, while the latter one achieved by call_once and reture a pointer. In my experiment, the Meyer's implimentation sames a little bit faster. But most project using the call_once approach for the most basic singleton implimentation, althought some small component of the project using Meyer's implimentation. I just wondering is there any principle to follow, and what's the pros and cons of this two different implimentation?

  • 1
    IMHO, basically, two implementations are the same. Meyer's implementation is a bit more elegant i would say. For example, second implementation has an unnecessary `initSingleton` method in this case. However, if the initialization would be more complicated this method would be useful too. – NutCracker Oct 11 '19 at 07:35
  • 1
    Meyer's implementation is sensible to "Destruction Order Fiasco", see [DOF](https://stackoverflow.com/questions/469597/destruction-order-of-static-objects-in-c) while the second is memory leaking sensible... – Jean-Baptiste Yunès Oct 11 '19 at 07:36
  • 2
    The only destruction-order risk with Meyer is if your destruction depend on static objects that are not also "proper" singletons, such as `std::cout` and `std::cin`. The second method provides no opportunity for clean-up code in the destructor. – molbdnilo Oct 11 '19 at 07:43

1 Answers1

4

The call_once version keeps a pointer to the instance and create it using new. Since no delete is ever called on the pointer, this solution poses some troubles if one needs sensible code to be run in the instance destructor. Apart from the annoying dangling pointer at process exit, one can consider using it if the instance destructor is just a default one like in your example.

p-a-o-l-o
  • 9,807
  • 2
  • 22
  • 35