[转]C++回顾之static与单例模式

来源:互联网 发布:企业域名是什么意思 编辑:程序博客网 时间:2024/06/14 23:56

http://blog.csdn.net/ab198604/article/details/19196315


单例模式是应用最多的一种设计模式,它要求每个类有且只能有一个实例对象,

所以用C++设计一个单例模式的方法如下:

        1 构造函数声明为私有;   这样就保证了不能随意构造一个对象

        2 将拷贝构造函数与等号运算符声明为私有,并不提供他们的实现; 即禁止对象被拷贝。

        3 在类中声明一个静态的全局访问接口;

        4 声明一个静态的私有实例化指针;

        

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class Singleton  
  2. {  
  3. public:  
  4.     //全局访问接口  
  5.     static Singleton *GetInstance()  
  6.     {  
  7.         if( instance_ == NULL )  
  8.         {  
  9.             instance_ = new Singleton;  
  10.         }  
  11.         return instance_;  
  12.     }  
  13.   
  14.     ~Singleton()  
  15.     {  
  16.         cout << "~Singleton"<< endl;  
  17.     }  
  18.   
  19. private:  
  20.     Singleton(const Singleton& other);  
  21.     Singleton & operator=(const Singleton & other);  
  22.     Singleton()  
  23.     {  
  24.           cout << "Singleton"<<endl;  
  25.     }  
  26.   
  27.   
  28.     static Singleton *instance_; //引用性声明  
  29. };  
  30.   
  31. Singleton * Singleton::instance_; //定义性声明  
  32.   
  33. int main(void)  
  34. {  
  35.     Singleton *s1 = Singleton::GetInstance();  
  36.     Singleton *s2 = Singleton::GetInstance();  //s2的地址等于s1,即指向同一对象  
  37.   
  38.     //Singleton s3(*s1); //既然是单例模式,是不允许被拷贝的。编译会出错  
  39.   
  40.     return 0;  
  41. }  
        上面就是单例类模式的C++实现,但是上述代码还有一个缺陷:单例类中申请的一些资源没有被释放,如instance_指向的空间没有被回收。一共有两种解决方式:

        第一种解决方式:

        

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class Singleton  
  2. {  
  3.     ...  
  4.     //提供一个回收接口,在应用中显示调用回收资源  
  5.     static void Free()  
  6.     {  
  7.         delete instance_;  
  8.     }  
  9.   
  10.     ....  
  11. };  
  12.   
  13. int main()  
  14. {  
  15.     ...  
  16.     Singleton::Free(); //要显示调用进行资源回收  
  17. }  
        这种方式虽然能实现功能,但是不太方便,每次都要手动回收资源,这是它的缺点。

        第二种解决方式:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class Singleton  
  2. {  
  3.     ...  
  4. public:  
  5.     class Garbo //资源回收机制  
  6.     {  
  7.     public:  
  8.         ~Garbo()  
  9.         {  
  10.             if( Singleton::instance_ != NULL )  
  11.             {  
  12.                 delete instance_;  
  13.             }  
  14.         }  
  15.     };  
  16.   
  17.     ...  
  18. private:  
  19.     ...  
  20.     static Garbo garbo_;  //引用性声明  
  21. };  
  22.   
  23. Singleton::Garbo Singleton::garbo_;//定义性声明  
        这种方式提供的处理方式显然要比第一种方式来的要便捷,因为它依靠内部提供的Garbo嵌套类来提供服务,当Singleton类生命周期结束时,Garbo的类对象garbo_也要销毁,它将调用析构函数,而在析构函数中又自动地释放了Singleton单例类申请的一些资源,这种实现就比较智能化。不需要手动释放资源。这是它的优势。

        

        下面提供另一种实现C++单例类模式的方法:

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. class Singleton  
  2. {  
  3.  public:  
  4.     static Singleton& GetInstance()  
  5.     {  
  6.         static Singleton instance_;                   return instance_;  
  7.     }  
  8.   
  9.     ~Singleton()  
  10.     {  
  11.         cout << "~Singleton"<<endl;  
  12.     }  
  13. private:  
  14.   
  15.     Singleton()  
  16.     {  
  17.         cout << "Singleton "<<endl;  
  18.     }  
  19.     Singleton(const Singleton &other);  
  20.     Singleton & operator=(const Singleton &other);  
  21. };  
        这种实现方式利用了static修改函数内部的变量,当第一次调用GetInstance函数时,系统将构造一个Singleton对象,在后续再次调用这个函数时,系统不再执行这个语句,也就不会再构造Singleton类对象了,而直接返回instance_本身。另外,当Singleton类对象生命周期结束时,对象会自动调用析构函数销毁,这里也就不存在申请资源之类的了,需要注意的是GetInstance()函数返回的是引用,这样就不会调用拷贝构造函数了,使用时也应该声明Singleton的引用,如下:

       

[cpp] view plain copy
 在CODE上查看代码片派生到我的代码片
  1. int main()  
  2. {  
  3.     Singleton &s1 = Singleton::GetInstance();  
  4.     Singleton &s2 = Singleton::GetInstance(); //s1与s2是同一对象的引用  
  5.   
  6.     return 0;  
  7. }  

以上方案单线程没有问题,可是到了多线程就出问题了,下面看个线程安全的版本

#include <windows.h> #define CLASS_UNCOPYABLE(classname) \private:\classname (const classname&);\classname& operator=(const classname&);\class Mutex {    CLASS_UNCOPYABLE(Mutex) public:    Mutex() :_cs() { InitializeCriticalSection(&_cs); }    ~Mutex() { DeleteCriticalSection(&_cs); }     void lock() { EnterCriticalSection(&_cs); }     void unlock() { LeaveCriticalSection(&_cs); } private:     CRITICAL_SECTION _cs; };  class Lock {    CLASS_UNCOPYABLE(Lock) public:    explicit Lock(Mutex& cs) :_cs(cs) { _cs.lock(); }     ~Lock() { _cs.unlock(); } private:     Mutex& _cs; };

template <class T> class CSingleton {   CLASS_UNCOPYABLE(CSingleton) public: static T& Instance(){ // Unique point of access       if (0 == _instance) {          Lock lock(_mutex);             if (0 == _instance) {               _instance = new T();               atexit(Destroy);            }        }        return *_instance;     } protected: CSingleton(void){}  ~CSingleton(void){} private: static void Destroy() { // Destroy the only instance if ( _instance != 0 ) { delete _instance; _instance = 0; } }    static Mutex _mutex;    static T * volatile _instance; // The one and only instance };template <class T>Mutex CSingleton<T>::_mutex; template <class T>T* volatile CSingleton<T>::_instance = 0;



0 0
原创粉丝点击