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

本文结合一些已有的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  

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

猜你喜欢

转载自blog.csdn.net/zztan/article/details/54691809