成人午夜视频全免费观看高清-秋霞福利视频一区二区三区-国产精品久久久久电影小说-亚洲不卡区三一区三区一区

c++單例模式---超詳細(xì)



一.概述:

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

  因?yàn)樵谠O(shè)計(jì)或開發(fā)中,肯定會(huì)有這么一種情況,一個(gè)類只能有一個(gè)對(duì)象被創(chuàng)建,如果有多個(gè)對(duì)象的話,可能會(huì)導(dǎo)致狀態(tài)的混亂和不一致。這種情況下,單例模式是最 恰當(dāng)?shù)慕鉀Q辦法。有很多地方需要這樣的功能模塊,如系統(tǒng)的日志輸出,GUI應(yīng)用必須是單鼠標(biāo),MODEM的聯(lián)接需要一條且只需要一條電話線,操作系統(tǒng)只能有一個(gè)窗口管理器,一臺(tái)PC連一個(gè)鍵盤。單例模式有很多種實(shí)現(xiàn)方式,各自的特性不相同,使用的情形也不相同。今天要實(shí)現(xiàn)的是常用的三種,分別是餓漢式、懶漢式和多線程式。

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



二.懶漢式實(shí)現(xiàn)單例模式:

懶漢式的特點(diǎn)是延遲加載,懶漢么,很懶,它只在要用到實(shí)例時(shí)才加載實(shí)例。

 /****************************************                                   
  2     > File Name:lanhan.cpp
  3     > Author:xiaoxiaohui
  4     > mail:1924224891@qq.com
  5     > Created Time:2016年05月07日 星期六 15時(shí)01分25秒
  6 ****************************************/
  7 
  8 #include<iostream>
  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一個(gè)對(duì)象 后者返回原來(lái)的兩個(gè)對(duì)象(所以保證了只有一個(gè)對(duì)象生成)   
 25     }
 26  
 27 }
 28

上面的這一實(shí)現(xiàn)存在內(nèi)存泄露問題,因?yàn)闆]有釋放_(tái)instance指針,下面為懶漢式的改進(jìn)版:

 8 #include<iostream>
  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)變量會(huì)在程序結(jié)束時(shí)調(diào)用它的析構(gòu)函數(shù)
 31 public:
 32     static Singleton* GetInstance()
 33     {
 34         if(_instance == NULL)
 35         {
 36             _instance = new Singleton();
 37         }
 38         return _instance;   //如果非空則new一個(gè)對(duì)象 后者返回原來(lái)的兩個(gè)對(duì)象(所以保證了只有一個(gè)對(duì)象生成)   
 39     }
 40 
 41 }

該實(shí)現(xiàn)會(huì)在程序結(jié)束時(shí)調(diào)用靜態(tài)變量的析構(gòu)函數(shù),從而delete了唯一的Singleton對(duì)象。

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

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

 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;   //靜態(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)變量會(huì)在程序結(jié)束時(shí)調(diào)用它的析構(gòu)函數(shù)
 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一個(gè)對(duì)象 后者返回原來(lái)的兩個(gè)對(duì)象(所以保證了只有一個(gè)對(duì)象生成)   
 45     }
 46 
 47 }
 48

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

 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;   //靜態(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)變量會(huì)在程序結(jié)束時(shí)調(diào)用它的析構(gòu)函數(shù)
 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一個(gè)對(duì)象 后者返回原來(lái)的兩個(gè)對(duì)象(所以保證了只有一個(gè)對(duì)象生成)   
 48     }
 49 
 50 }

這樣只有沒有Singleton實(shí)例時(shí)才會(huì)進(jìn)入加鎖的代碼,而當(dāng)有Singleton實(shí)例時(shí)不需要進(jìn)入加鎖的代碼中,直接返回已存在的實(shí)例就行了。



三.餓漢式的單例模式:在一開始就創(chuàng)建實(shí)例,要用時(shí)直接返回即可。餓汗式的單例模式?jīng)]有線程安全問題,因?yàn)樗跃€程都只能訪問一個(gè)已存在的對(duì)象,無(wú)論線程怎么調(diào)度都不會(huì)有多個(gè)對(duì)象出現(xiàn)。因?yàn)閷?duì)象是一個(gè)靜態(tài)變量(不是指針),會(huì)在程序結(jié)束時(shí)自動(dòng)調(diào)用它的析構(gòu)函數(shù),所以不用考慮內(nèi)存泄露問題。

餓汗式的特點(diǎn):代碼簡(jiǎn)單,不會(huì)出現(xiàn)內(nèi)存泄露,是線程安全的。

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

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

但這個(gè)實(shí)現(xiàn)存在問題,Singleton singleton = Singleton :: GetInstance(),這么做就出現(xiàn)了一個(gè)類拷貝的問題,這就違背了單例的特性。產(chǎn)生這個(gè)問題原因在于:因?yàn)樵谶@里沒有實(shí)現(xiàn)拷貝構(gòu)造函數(shù),編譯器會(huì)為類生成一個(gè)默認(rèn)的拷貝構(gòu)造函數(shù),來(lái)支持類的拷貝。

解決方法:1.自己再定義一個(gè)拷貝構(gòu)造函數(shù)和operator=,這個(gè)拷貝構(gòu)造函數(shù)和operator=什么都不做。

2.返回一個(gè)Singleton指針。

下面為方法2的代碼:

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


總結(jié):?jiǎn)卫J竭m用于只允許一個(gè)實(shí)例存在的情況,它的實(shí)現(xiàn)必須滿足三個(gè)條件,一是必須在類中就定義一個(gè)實(shí)例;二是必須有一個(gè)公有的靜態(tài)方法來(lái)獲取該實(shí)例;三是構(gòu)造函數(shù)必須是私有的,來(lái)保證不容許別人通過(guò)調(diào)用構(gòu)造函數(shù)來(lái)生成一個(gè)實(shí)例。在實(shí)現(xiàn)時(shí)要注意內(nèi)存泄露問題,線程安全問題,性能問題。

文章名稱:c++單例模式---超詳細(xì)
URL網(wǎng)址:http://jinyejixie.com/article40/psioho.html

成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供小程序開發(fā)、微信小程序、搜索引擎優(yōu)化、App設(shè)計(jì)、面包屑導(dǎo)航定制開發(fā)

廣告

聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來(lái)源: 創(chuàng)新互聯(lián)

網(wǎng)站建設(shè)網(wǎng)站維護(hù)公司
措美县| 柞水县| 上虞市| 图木舒克市| 崇仁县| 洛扎县| 洛扎县| 茌平县| 永清县| 鹤山市| 茶陵县| 西乌珠穆沁旗| 万山特区| 察雅县| 桃江县| 永嘉县| 农安县| 五华县| 井陉县| 定陶县| 新竹市| 集贤县| 巧家县| 温宿县| 临猗县| 余姚市| 湘潭市| 安龙县| 万盛区| 都匀市| 鄄城县| 苏尼特左旗| 荔波县| 高淳县| 广宗县| 武威市| 桂平市| 正蓝旗| 谢通门县| 昌都县| 沈丘县|