Blog.csdn.net/king4577577…

Recently, I wrote code because of negligence of singleton judgment, resulting in a bug when the program switched quickly and started many times. I took this opportunity to comb through the construction mode of several singleton modes. The singleton pattern exists to ensure that a class has only one instance and to provide a global access point to it, which is shared by all program modules.

  • Solution 1 (Lazy)

One way to do this is to define a singleton class that uses the class’s private static pointer variable to point to a unique instance of the class and uses a public static method to get that instance. The singleton pattern provides a solution to the problem by managing its unique instance through the class itself. The only instance is a normal object of the class, but the class is designed so that it can create only one instance and provide global access to that instance. The Singleton class hides the creation of the instance in static member functions.

Class CSingleton {private: CSingleton() // Constructor is private {} static CSingleton *m_pInstance; Public: static CSingleton * GetInstance() {if(m_pInstance == NULL); return m_pInstance; }};Copy the code

The only way for a user to access a unique instance is the GetInstance() member function. Without this function, any attempt to create an instance will fail because the constructor of the class is private. GetInstance() uses lazy initialization, which means that its return value is created when the function is first accessed. All calls after GetInstance() return a pointer to the same instance. The CSingleton singleton class defined above has the following three characteristics :(1) it has a private static pointer m_pInstance to a unique instance; (2 there is a public function that gets this unique instance and creates it if needed; (3) Constructor is private, external cannot create instance of the class; One problem with this implementation is the release of the m_pInstance variable, which is the instance destructor problem. Although we can call GetInstance () at the end of the program and delete the pointer returned by it, this method is not only tedious, but also the caller forgets. It can cause a lot of problems.

One solution to this problem is to define a static global variable in this class. We know that at the end of the program, the system automatically destructs all global variables. The system also destructs all static member variables of a class as if they were global variables. We can define one of these static member variables in the CSingleton singleton class, removing instances of the singleton class in its destructor.

class CSingleton { private: CSingleton() { } static CSingleton *m_pInstance; Class CGarbo // Its only job is to remove the instance of CSingleton in the destructor {public: ~CGarbo() { if(CSingleton::m_pInstance) delete CSingleton::m_pInstance; }}; static CGarbo Garbo; // Define a static member variable whose destructor public is automatically called when the program ends: Static CSingleton * GetInstance() {if(m_pInstance == NULL); return m_pInstance; }};Copy the code
  • Solution 2 (Hungry)

If you’re not satisfied with adding a class static object inside a singleton class, you can also use the local static variable method construct:

Class CSingleton {private: CSingleton() // Constructor is private {} public: static CSingleton & GetInstance() { static CSingleton instance; // local static variable return instance; }};Copy the code

Singleton = Singleton :: GetInstance(); Singleton :: GetInstance(); The compiler generates a default constructor for the class to support copying the class. This violates the singleton property, so we can change it slightly and return a pointer:

Class CSingleton {private: CSingleton() // Constructor is private {} public: static CSingleton * GetInstance() { static CSingleton instance; // local static variable return &instance; }};Copy the code

You can also prevent the compiler from doing so by displaying a constructor that declares a copy of the class, overloading the = operator.

See Effective C++, chapter 6. Functions that are not automatically generated are explicitly rejected.

To override functionality automatically provided by the compiler, the corresponding member function can be declared private and not implemented.

Class CSingleton {private: CSingleton() // Constructor is private {} CSingleton(const CSingleton &); CSingleton & operator = (const CSingleton &); public: static CSingleton & GetInstance() { static CSingleton instance; // local static variable return instance; }};Copy the code