真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯網站制作重慶分公司

c++單例模式---超詳細



一.概述:

創(chuàng)新互聯專注于企業(yè)成都全網營銷、網站重做改版、龍華網站定制設計、自適應品牌網站建設、H5響應式網站、電子商務商城網站建設、集團公司官網建設、外貿營銷網站建設、高端網站制作、響應式網頁設計等建站業(yè)務,價格優(yōu)惠性價比高,為龍華等各大城市提供網站開發(fā)制作服務。

  因為在設計或開發(fā)中,肯定會有這么一種情況,一個類只能有一個對象被創(chuàng)建,如果有多個對象的話,可能會導致狀態(tài)的混亂和不一致。這種情況下,單例模式是最 恰當的解決辦法。有很多地方需要這樣的功能模塊,如系統的日志輸出,GUI應用必須是單鼠標,MODEM的聯接需要一條且只需要一條電話線,操作系統只能有一個窗口管理器,一臺PC連一個鍵盤。單例模式有很多種實現方式,各自的特性不相同,使用的情形也不相同。今天要實現的是常用的三種,分別是餓漢式、懶漢式和多線程式。

  《設計模式》一書中的實現有三個要素,定義一個單例類,要使用類的私有靜態(tài)指針變量指向類的唯一實例(即在類中就生成一個對象),并用一個公有的靜態(tài)方法獲取該實例,并把構造函數定義為protected或private。



二.懶漢式實現單例模式:

懶漢式的特點是延遲加載,懶漢么,很懶,它只在要用到實例時才加載實例。

 /****************************************                                   
  2     > File Name:lanhan.cpp
  3     > Author:xiaoxiaohui
  4     > mail:1924224891@qq.com
  5     > Created Time:2016年05月07日 星期六 15時01分25秒
  6 ****************************************/
  7 
  8 #include
  9 using namespace std
 10 
 11 class Singleton
 12 {
 13 private:
 14     Singleton()
 15     {}
 16     static Singleton* _instace;   //靜態(tài)的  私有的
 17 public:
 18     static Singleton* GetInstace()
 19     {
 20         if(_instance == NULL)
 21         {
 22             _instance = new Singleton();
 23         }
 24         return _instance;   //如果非空則new一個對象 后者返回原來的兩個對象(所以保證了只有一個對象生成)   
 25     }
 26  
 27 }
 28

上面的這一實現存在內存泄露問題,因為沒有釋放_instance指針,下面為懶漢式的改進版:

 8 #include
  9 using namespace std
 10 
 11 class Singleton
 12 {
 13 private:
 14     Singleton()
 15     {}
 16     static Singleton* _instance;   //靜態(tài)的  私有的
 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;  //靜態(tài)變量會在程序結束時調用它的析構函數
 31 public:
 32     static Singleton* GetInstance()
 33     {
 34         if(_instance == NULL)
 35         {
 36             _instance = new Singleton();
 37         }
 38         return _instance;   //如果非空則new一個對象 后者返回原來的兩個對象(所以保證了只有一個對象生成)   
 39     }
 40 
 41 }

該實現會在程序結束時調用靜態(tài)變量的析構函數,從而delete了唯一的Singleton對象。

使用這種方法釋放單例對象有以下特征:
1.在單例類內部定義專有的嵌套類。
2.在單例類內定義私有的專門用于釋放的靜態(tài)成員。
3.利用程序在結束時析構全局變量的特性,選擇最終的釋放時機。

但是現在還有問題,如果在多線程環(huán)境下,因為“if(_instance == NULL)”并不是原子的,會存在線程安全問題(如果一個線程剛剛判斷了指針為空,這時另一個線程的優(yōu)先級更高或者其它原因,打斷了原來線程的執(zhí)行,再次判斷指針也會為空,所以會出現兩個實例)下面為多線程環(huán)境下的懶漢式單例模式:

 8 #include
  9 #include
 10 #include
 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;   //靜態(tài)的  私有的
 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;  //靜態(tài)變量會在程序結束時調用它的析構函數
 35 public:
 36     static Singleton* GetInstance()
 37     {
 38         pthread_mutex_lock(&lock);
 39         if(_instance == NULL)
 40         {
 41             _instance = new Singleton();
 42         }
 43         pthread_mutex_unlock(&lock);
 44         return _instance;   //如果非空則new一個對象 后者返回原來的兩個對象(所以保證了只有一個對象生成)   
 45     }
 46 
 47 }
 48

但現在還有問題,當有大量的線程時,只會有一個線程進入互斥鎖,然后執(zhí)行下面的代碼而其它線程只能等待,并且加鎖是一個繁重的過程,這樣會導致加很多次鎖,這樣就太不高效了。下面是高效版的多線程環(huán)境下的懶漢式單例模式:

 8 #include
  9 #include
 10 #include
 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;   //靜態(tài)的  私有的
 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;  //靜態(tài)變量會在程序結束時調用它的析構函數
 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;   //如果非空則new一個對象 后者返回原來的兩個對象(所以保證了只有一個對象生成)   
 48     }
 49 
 50 }

這樣只有沒有Singleton實例時才會進入加鎖的代碼,而當有Singleton實例時不需要進入加鎖的代碼中,直接返回已存在的實例就行了。



三.餓漢式的單例模式:在一開始就創(chuàng)建實例,要用時直接返回即可。餓汗式的單例模式沒有線程安全問題,因為所以線程都只能訪問一個已存在的對象,無論線程怎么調度都不會有多個對象出現。因為對象是一個靜態(tài)變量(不是指針),會在程序結束時自動調用它的析構函數,所以不用考慮內存泄露問題。

餓汗式的特點:代碼簡單,不會出現內存泄露,是線程安全的。

  1 /****************************************
  2     > File Name:erhan.cpp
  3     > Author:xiaoxiaohui
  4     > mail:1924224891@qq.com
  5     > Created Time:2016年05月07日 星期六 16時10分56秒
  6 ****************************************/
  7 
  8 #include
  9 using namespace std
 10 
 11 
 12 class Singleton
 13 {
 14 private:
 15     Singleton()
 16     {}
 17     static Singleton instance ;    //靜態(tài)變量只會有一份數據存在 從而保證只有一個實例
 18 public:
 19     static Singleton& GetInstance()
 20     {
 21         return instance;                                                   
 22     }   
 23 }

聲明一個局部的靜態(tài)變量,而靜態(tài)變量在全局范圍內只有一份數據,所以無論調用多少此GetInstance,返回的都是那一個實例。

但這個實現存在問題,Singleton singleton = Singleton :: GetInstance(),這么做就出現了一個類拷貝的問題,這就違背了單例的特性。產生這個問題原因在于:因為在這里沒有實現拷貝構造函數,編譯器會為類生成一個默認的拷貝構造函數,來支持類的拷貝。

解決方法:1.自己再定義一個拷貝構造函數和operator=,這個拷貝構造函數和operator=什么都不做。

2.返回一個Singleton指針。

下面為方法2的代碼:

  8 #include
  9 using namespace std
 10 
 11 
 12 class Singleton
 13 {
 14 private:
 15     Singleton()
 16     {}
 17     static Singleton instance ;    //靜態(tài)變量只會有一份數據存在 從而保證只有一個實例
 18 public:
 19     static Singleton* GetInstance()
 20     {
 21         return &instance;                                                   
 22     }   
 23 }


總結:單例模式適用于只允許一個實例存在的情況,它的實現必須滿足三個條件,一是必須在類中就定義一個實例;二是必須有一個公有的靜態(tài)方法來獲取該實例;三是構造函數必須是私有的,來保證不容許別人通過調用構造函數來生成一個實例。在實現時要注意內存泄露問題,線程安全問題,性能問題。


文章標題:c++單例模式---超詳細
本文網址:http://weahome.cn/article/psioho.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部