C + + Singleton mode---super verbose

Source: Internet
Author: User

I. Overview:

Because in design or development, there must be a situation where a class can have only one object created, and if there are multiple objects, it can cause confusion and inconsistencies in state. In this case, the singleton pattern is the most appropriate solution. There are many places need such a function module, such as the log output of the system, the GUI application must be a single mouse, the modem connection requires one and only need a phone line, the operating system can only have a window manager, a PC with a keyboard. There are many ways to implement a singleton pattern, with different characteristics and different situations. Today to achieve is the common three kinds, are a hungry man, lazy and multi-line program.

The implementation in design mode has three elements, defines a singleton class, uses the class's private static pointer variable to point to a unique instance of the class (that is, generates an object in the Class), obtains the instance with a public static method, and defines the constructor as protected or private.


Two. Lazy-type implementation of the single-case mode:

Lazy style is the lazy load, lazy, it is very idle, it only to use the instance to load the instance.

 /****************************************                                       2     > file name: lanhan.cpp  3     > author:xiaoxiaohui  4      > mail:[email protected]  5     >  created time:2016 May 07   Saturday  15 01 minutes, 25 seconds   6 ************************************** **/  7   8  #include <iostream>  9 using namespace  std 10  11 class singleton 12 { 13 private: 14      singleton ()  15     {} 16      Static singleton* _instace;   //Static    Private  17 public: 18      Static singleton* getinstace ()  19     { 20          if (_instance == null)  21          { 22              _instance = new singleton (); 23          } 24         return _instance;   / /If not empty then new an object   the latter returns the original two objects (so that only one object generation is guaranteed)     25     } 26    27 } 28

There is a memory leak problem with this implementation on the

, because the _instance pointer is not released, and the following is a lazy-style improved version:

 8  #include <iostream>  9 using namespace std 10  11  class singleton 12 { 13 private: 14     singleton ()  15     {} 16     static singleton* _ instance;   //Static    Private  17  18     class  del 19     { 20     public: 21          ~del ()  22          { 23             if (Singleton::_instance  != null)  24             {  25                  Delete singleton::_instance; 26                  Singleton::_instance = NULL; 27              } 28         } 29      } 30     static del d;  // A static variable invokes its destructor at the end of the program  31 public: 32     static Singleton*  getinstance ()  33     { 34          if (_instance == null)  35         { 36              _instance = new  Singleton (); 37         } 38          return _instance;   //if not NULL then the new object   The latter returns the original two objects (so that only one object generation is guaranteed)     39      } 40  41 }

The implementation calls the static variable's destructor at the end of the program, and deletes the unique singleton object.

Using this method to release a singleton object has the following characteristics:
1. Define a proprietary nested class inside a singleton class.
2. In a singleton class, define a private, static member dedicated to deallocation.
3. Using the program at the end of the analysis of the characteristics of global variables, select the final release time.


But now there is a problem, if in a multithreaded environment, because "if (_instance = = NULL)" Is not atomic, there will be a thread-safety problem (if a thread has just judged that the pointer is empty, then another thread has higher priority or other reasons, interrupted the original thread execution, Again, the pointer will also be empty, so there will be two instances) the following is a lazy singleton pattern in a multithreaded environment:

 8  #include <iostream>  9  #include <stdlib.h> 10  #include < pthread.h> 11  12 pthread_mutex_t lock = pthread_mutex_initializer;  13 using namespace std 14  15 class singleton 16 {  17 private: 18     singleton ()  19     { } 20     static singleton* _instance;   //static     Private  21  22     class del 23      { 24     public: 25          ~del ()  26         { 27              if (singleton::_instance != null)  28              { 29                  delete Singleton::_instance; 30                  singleton::_instance =  null; 31             } 32          } 33     } 34      static del d;  //static variable calls its destructor at the end of the program  35 public: 36      static singleton* getinstance ()  37     {  38         pthread_mutex_lock (&lock); 39          if (_instance == null)  40          {&Nbsp;41             _instance = new  singleton (); 42         } 43          pthread_mutex_unlock (&lock); 44          return _instance;   //if not NULL then the new object   The latter returns the original two objects (so that only one object is generated)     45     } 46  47 } 48

But there is still a problem, when there are a large number of threads, only one thread enters the mutex, and then executes the following code while the other threads wait only, and locking is a heavy process, which results in multiple locks, which is too much less efficient. The following is a lazy singleton pattern in the efficient version of multithreaded environments:

 8  #include <iostream>  9  #include <stdlib.h> 10  #include < pthread.h> 11  12 pthread_mutex_t lock = pthread_mutex_initializer;  13 using namespace std 14  15 class singleton 16 {  17 private: 18     singleton ()  19     { } 20     static singleton* _instance;   //static     Private  21  22     class del 23      { 24     public: 25          ~del ()  26         { 27              if (singleton::_instance != null)  28              { 29                  delete Singleton::_instance; 30                  singleton::_instance =  null; 31             } 32          } 33     } 34      static del d;  //static variable calls its destructor at the end of the program  35 public: 36      static singleton* getinstance ()  37     {  38         if (_instance == null)  39          { 40               pThread_mutex_lock (&lock); 41               if (_instance == null)  42               { 43                  _instance = new singleton (); 44               } 45               pthread_mutex_unlock (&lock); 46          } 47          return _instance;   //if not NULL then the new object   The latter returns the original two objects (so that only one object generation is guaranteed)      48     } 49  50 }

This will only enter the lock code when there is no singleton instance, and when there is a singleton instance, it is not necessary to go into the lock code and return the existing instance directly.


Three. A hungry man-style singleton mode: Create an instance at the beginning and return it directly when you want. The hungry singleton mode does not have a thread safety problem, because so the thread can only access an existing object, no matter how the thread is dispatched, there will not be more than one object appearing. Because an object is a static variable (not a pointer), its destructor is called automatically at the end of the program, so there is no need to consider a memory leak issue.

The characteristics of the hungry sweat: The code is simple, there will be no memory leaks, is thread-safe.

  1 /****************************************  2     >  File Name:erhan.cpp  3     > Author:xiaoxiaohui   4     > mail:[email protected]  5      > created time:2016 May 07   Saturday  16 10 minutes, 56 seconds   6 **************** /  7   8  #include <iostream>  9  using namespace std 10  11  12 class singleton 13 {  14 private: 15     singleton ()  16     { } 17     static singleton instance ;    // Static variables will only have one copy of the data   thus guarantee only one instance  18 public: 19     static singleton & getinstance ()  20     { 21         return  instance;                                                      22      }    23 }

Declares a local static variable, and the static variable has only one copy of the global scope, so no matter how much this getinstance is called, the instance is returned.

However, there is a problem with this implementation,Singleton Singleton = Singleton:: getinstance (), so there is a class copy problem, which violates the characteristics of the singleton. The reason for this problem is that because the copy constructor is not implemented here, the compiler generates a default copy constructor for the class to support the copy of the class.

WORKAROUND: 1. Define a copy constructor and operator= yourself, and this copy constructor and operator= do nothing.

2. Returns a singleton pointer.

Here is the code for Method 2:

  8  #include <iostream>  9 using namespace std 10   11  12 class Singleton 13 { 14 private: 15      singleton ()  16     {} 17      static singleton instance ;    //static variables will only have one copy of the data   thus guarantee only one instance  18  public: 19     static singleton* getinstance ()  20      { 21         return & instance;                                                      22      }    23 } 


Summary: The singleton pattern is suitable for situations where only one instance is allowed, its implementation must satisfy three conditions, one must define an instance in the class, and the other must have a public static method to obtain the instance, and the constructor must be private to ensure that no one is allowed to generate an instance by calling the constructor. Be aware of memory leaks, thread safety issues, and performance issues when implemented.

This article is from "Narcissus" blog, please make sure to keep this source http://10704527.blog.51cto.com/10694527/1771034

C + + Singleton mode---super verbose

Related Article

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.