C++实现单例的5种方法总结

来源:互联网 发布:vb九九乘法表右上三角 编辑:程序博客网 时间:2024/06/16 15:54

本文结合一些已有的C++ 单例模式 设计方法,总结出了5种实现方式,并指出其中的使用特点和注意事项;

参考引用的文章链接:

  ++ 几种单例模式的写法

https://segmentfault.com/q/1010000004157283


一般情况下,为了实现单例我们都会想到使用 static 成员,下面#1是最基本的方式;

#1 静态指针成员:

 
    class Singleton{          private:              Singleton(){};              virtual ~Singleton(){};          public:              Singleton *Instance();          protect:              static Singleton *_instance;       };      //Singleton.h                  Singleton *Singleton::instance()      {                if(NULL == _instance){              _instance = new Singleton();          }          return _instance;      }      //Singleton.cpp  

构造时机: 运行时生成;

对象位置:   堆 

资源释放: new的单例对象,没有时机去释放;

线程安全: 否;  ---在单例构造过程可能重复,造成内存泄露;


#2 静态指针成员(改进型):

在#1的基础上解决存在的两个问题;

如果单例对象的构造实在运行时之前(也就是程序静态变量初始化时完成)就可以避免线程安全的问题;

    class Singleton{          public:              static Singleton *instance();          private:              Singleton();              virtual ~Singleton();              Singleton(const Singleton&){};              Singleton& operator=(const Singleton&){};          private:              class CGarbo{                  public:                      ~CGarbo()                      {                            if(Singleton::m_pInstance){                              delete m_pInstance;                          }                        }                };           private:              static Singleton *m_pInstance;              static CGarbo Garbo;      };      //Singleton.h                  Singleton::CGarbo Singleton::Garbo;      Singleton* Singleton::m_pInstance = new Singleton();            Singleton::Singleton()      {          printf("contructure funcation\n");      }            Singleton::~Singleton()      {          printf("deconstructure funcation\n");      }            Singleton* Singleton::instance()      {          return m_pInstance;      }      //Singleton.cpp

构造时机: 初始化时生成;

对象位置:   堆 

资源释放: 通过一个成员的析构函数来释放单例对象,;  非常巧妙, 但是m_pInstance指针和 Garbo两个成员的析构是否有先后顺序,如果指针先被释放(指针变量变成NULL?)那么单例对象还是没有机会被释放;  ---找时间确认一下,然后更新一下这个结果;

线程安全: 是;  ---初始化过程,没有线程竞争;


对比以上两种方式,可以看出静态初始化的时候构造单例对象,能够比较好的解决线程安全的问题; 但是资源释放的需要通过曲线救国的方式来解决;

那么能不能把单例对象也生成在静态区呢?这样释放的问题就可以由操作系统自动完成;

#3 静态成员对象

    class Singleton{          public:              static Singleton *instance();          private:              Singleton();              virtual ~Singleton();              Singleton(const Singleton&){};              Singleton& operator=(const Singleton&){};          private:              static Singleton m_instance;      };      //Singleton.h            Singleton Singleton::m_instance;            Singleton::Singleton()      {          printf("contructure funcation\n");      }            Singleton::~Singleton()      {          printf("deconstructure funcation\n");      }            Singleton *Singleton::instance()      {          return &m_instance;      }      //Singleton.cpp  

构造时机: 初始化时生成;

对象位置:  静态区

资源释放: 在程序结束时 自动释放静态区的 成员变量

线程安全: 是;

注意: 静态成员的初始化需要放到类外完成;  那么是否可以把静态对象在成员函数instance()内部生成呢?

#4 静态局部对象

 class Singleton{          public:              static Singleton *instance();          private:              Singleton();              virtual ~Singleton();              Singleton(const Singleton&){};              Singleton& operator=(const Singleton&){};       };      //Singleton.h             Singleton::Singleton()      {          printf("contructure funcation\n");      }            Singleton::~Singleton()      {          printf("deconstructure funcation\n");      }            Singleton *Singleton::instance()      {          static Singleton ins;        return &ins;      }   //Singleton.cpp


构造时机: 运行时生成; ---参考链接2 ;  --对于C++的局部类对象,是在函数第一次调用时生成;

对象位置:  静态区

资源释放: 在程序结束时 自动释放静态区的 成员变量
线程安全: 是(C++11);  ---参考链接2,, C++11标准针对局部静态对象的构造能保证线程安全(待查);

综合以上4中方式,单例对象的释放都是在程序结束时释放,

如果要求能够提供接口随时释放对象,那么就必须构造在堆上,然后提供显式的destroy接口;

#5 静态指针成员(动态释放)

    #ifndef __MUTEX_H__      #define __MUTEX_h__      #include <pthread.h>            class Mutex{        private:              pthread_mutex_t m_mutex;          public:              Mutex();              virtual ~Mutex();          private:              Mutex(const Mutex&){};              Mutex& operator=(const Mutex&){};          public:              int lock();              int unlock();              int trylock();            };      #endif //__MUTEX_H__      //Mutex.h                  #include "Mutex.h"            Mutex::Mutex()      {          pthread_mutex_init(&m_mutex, NULL);      }            Mutex::~Mutex()      {          pthread_mutex_destroy(&m_mutex);      }            int Mutex::lock()      {          return  pthread_mutex_lock(&m_mutex);      }            int Mutex::unlock()      {          return pthread_mutex_unlock(&m_mutex);      }            int Mutex::trylock()      {          return pthread_mutex_trylock(&m_mutex);      }      //Mutex.cpp            //单例类      #ifndef __SINGLETON_H__      #defile __SINGLETON_H__      #include "Mutex.h"      class Singleton{            public:          static Singleton *instance();          static void destroy();            private:          Singleton();          virtual ~Singleton();           Singleton(const Singleton&){};           Singleton& operator=(const Singleton&){};                private:          static Singleton *m_pInstance;          static Mutex m_Mutex;      };      #endif //__SINGLETON_H__      //Singleton.h                  Singleton* Singleton::m_pInstance = NULL;      Mutex Singleton::m_Mutex;            Singleton::Singleton()      {      //do something      }            Singleton::~Singleton()      {      //do something      }            Singleton* Singleton::instance()      {           if(NULL == m_pInstance){                m_Mutex.lock();                if(NULL == m_pInstance){                     m_pInstance = new Singleton();                }                m_Mutex.unlock();           }           return m_pInstance;      }            void Singleton::destroy()      {           if(m_pInstance){                m_Mutex.lock();                if(m_pInstance){                     delete m_pInstance;                     m_pInstance = NULL;                }                m_Mutex.unlock();           }      }      //Singleton.cpp  

当然 也可以吧 静态成员指针放到接口函数里面作为局部静态变量 和局部静态对象;

0 0