1

I have a My_Singleton global object singleton_obj that I want to ensure that it is properly initialized before it is used and there is only a single instance of it. I have learned about Nifty counter here, and I found some other answers about including std::ios_base::Init object in the class can achieve the same effect.

/*My_Singleton.h */
#include <iostream>
class My_Singleton
{
    My_Singleton(My_Singleton&&) =delete;
    My_Singleton& operator=(My_Singleton&&) =delete;
    My_Singleton(My_Singleton const&) =delete;
    My_Singleton& operator=(My_Singleton const&) =delete;
    std::ios_base::Init initalizer;
public: 
    My_Singleton() =default;
    ~My_Singleton() =default;
};

extern My_Singleton singleton_obj;

/*My_Singleton.cpp*/
#include "My_Singleton.h"
My_Singleton singleton_obj;

My question are:
1. Is this the correct way of doing it? If not, please provide a fix
2. How does std::ios_base::Init implemented?

sz ppeter
  • 1,698
  • 1
  • 9
  • 21

1 Answers1

1

I want to ensure that it is properly initialized before it is used and there is only a single instance of it

Is this the correct way of doing it?

No. std::ios_base::Init is used to order initialization of standard streams cout cin etc. The way you used it would make sure that standard streams are initialized before your object is initialized and destroyed after your object is destroyed.

If not, please provide a fix

The usual way to protect against static initialization fiasco is to provide a function that returns a reference to an object with static storage duration. Because the object with static storage duration will be initialized when entering the function, such function protects against the fiasco.

    My_Singleton& singleton_obj() {
       static My_Singleton obj;
       return obj;
    }

Placing such function inside your class and making constructor private will effectively disallow constructing other instances of this object.

How to implement a singleton with only one instance can be found in numerous places on the web, ex. this stackoverflow answer has ready-to-use pattern.

How does std::ios_base::Init implemented?

The constructor of std::ios_base::Init calls placement new on standard streams. That way, calling std::ios_base::Init::Init() will make sure, that standard streams are initialized. It has a counter, so it calls the placement new only once and destroys standard streams only when the counter reaches 0.

The implementation in libstdc++ can be found ios_init.cc, variables are defined in ios.cc and class definition is in bits/ios_base.h. Each transaction unit that uses streams has it's own static ios_base::Init __ioinit object.

The implementation in libc++ can be found in iostream.cpp, global object is declared in the same file and class definition is in include/ios.

Community
  • 1
  • 1
KamilCuk
  • 120,984
  • 8
  • 59
  • 111