青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品

#ant

The dreams in which I'm dying are the best I've ever had...

非完美C++ Singleton實(shí)現(xiàn)[1]

Singleton模式是一種非常簡(jiǎn)單的設(shè)計(jì)模式,這種模式很常用也很容易被濫用。當(dāng)你設(shè)計(jì)應(yīng)用程序的時(shí)候,經(jīng)常會(huì)遇到某些對(duì)象在整個(gè)程序的生命周期應(yīng)該僅有一個(gè)實(shí)例的情況,比如File System,Graphic System,Logging Utility,這時(shí)候就可以用到Singleton模式。Singleton模式在GOF中描述如下:

        Ensure a class only has one instance, and provide a global point of access to it.

Singleton模式的定義很簡(jiǎn)單,實(shí)現(xiàn)也有N多種,但是卻很難找到一個(gè)稱得上“完美”的。實(shí)現(xiàn)一個(gè)完美的Singleton比想象中要難的多,下面探索性的來實(shí)現(xiàn)一個(gè)非完美的。

1.典型實(shí)現(xiàn)
在C++中,Singleton模式的典型實(shí)現(xiàn)如下:

 1 // Header file Singleton.h
 2 class  Singleton {
 3 public
:
 4     static Singleton& Instance() { // Unique point of access

 5         if (0 ==  _instance)
 6             _instance = new
 Singleton();
 7         return *
_instance;
 8 
    }
 9     void
 DoSomething();
10 private
:
11     Singleton(); // Prevent clients from creating a new Singleton

12     ~Singleton(); // Prevent clients from deleting a Singleton
13     Singleton(const Singleton&); // Prevent clients from copying a Singleton
14     Singleton& operator=(const Singleton& );
15 private
:
16     static Singleton *_instance; // The one and only instance

17  };
18 

19 // Implementation file Singleton.cpp
20 Singleton* Singleton::_instance = 0;


通過將Singleton的構(gòu)造函數(shù)設(shè)為private可以禁止客戶代碼直接創(chuàng)建Singleton對(duì)象,除此之外,Singleton的copy constructor和copy assignment operator都為private且僅有聲明沒有實(shí)現(xiàn),禁止了客戶代碼拷貝Singleton對(duì)象。唯一可以創(chuàng)建Singleton對(duì)象的是Singleton自己的靜態(tài)成員函數(shù)Instance,這樣就在編譯器保證了Singleton實(shí)例的唯一性。上面這些是在C++中實(shí)現(xiàn)Singleton模式最基本的要點(diǎn)。

Instance方法保證只有在第一次調(diào)用時(shí)才會(huì)生成Singleton對(duì)象,以后的調(diào)用只是簡(jiǎn)單返回唯一的已存在的實(shí)例。Instance方法實(shí)際上實(shí)現(xiàn)的是懶惰初始化(lazy initialize),如果程序中根本沒有用到Singleton對(duì)象,也就根本不會(huì)產(chǎn)生Singleton的實(shí)例,這在Singleton對(duì)象很少使用且創(chuàng)建Singleton對(duì)象開銷比較大的情況下特別有用。

客戶代碼現(xiàn)在可以這樣使用Singleton:

1 Singleton &=  Singleton::Instance();
2 s.DoSomething();


還需要說明的是Singleton的析構(gòu)函數(shù),析構(gòu)函數(shù)也為private可以禁止客戶寫出如下代碼。如果某個(gè)客戶寫出了如下代碼,隨后的對(duì)Singleton的訪問就會(huì)導(dǎo)致為定義行為,因?yàn)镾ingleton對(duì)象已經(jīng)不存在。

1 Singleton *= & Singleton::Instance();
2 delete p;


2.引入smart pointer
上面的實(shí)現(xiàn)算是一個(gè)好的實(shí)現(xiàn)嗎?當(dāng)然不是,或許連一個(gè)正確的實(shí)現(xiàn)都算不上。如果你想湊合,當(dāng)然沒問題,上面的代碼大多數(shù)情況下可以工作的很好。也許你已經(jīng)注意到了一些問題,比如說在上面的代碼中只有new沒有delete。是的,你說會(huì)發(fā)生memory leak對(duì)吧,其實(shí)memory leak都不是主要的問題,所有的現(xiàn)代操作系統(tǒng)在進(jìn)程結(jié)束的時(shí)候都會(huì)對(duì)內(nèi)存很好的進(jìn)行回收。比memory leak更值得讓人擔(dān)憂的是resource leak,如果Singleton在構(gòu)造函數(shù)中請(qǐng)求了某些資源:網(wǎng)絡(luò)連接,文件句柄,數(shù)據(jù)庫(kù)連接等。這些資源將得不到釋放。

唯一修正resource leak的方法就是在程序結(jié)束的時(shí)候delete _instance。當(dāng)然了,用smart pointer再好不過,在這里用auto_ptr就可以滿足需要了(如果你還不知道smart_ptr是什么,花點(diǎn)時(shí)間熟悉C++標(biāo)準(zhǔn)庫(kù)吧),修改后的代碼如下:

 1 // Header file Singleton.h
 2 class  Singleton {
 3 public
:
 4     static Singleton& Instance() { // Unique point of access

 5         if (0 ==  _instance.get())
 6             _instance.reset(new
 Singleton());
 7         return *
(_instance.get());
 8 
    }
 9     void
 DoSomething(){}
10 private
:
11     Singleton(){} // Prevent clients from creating a new Singleton

12     ~Singleton(){} // Prevent clients from deleting a Singleton
13     Singleton(const Singleton&); // Prevent clients from copying a Singleton
14     Singleton& operator=(const Singleton& );
15 private
:
16     friend auto_ptr<Singleton>
;
17     static auto_ptr<Singleton> _instance; // The one and only instance

18  };
19 

20 // Implementation file Singleton.cpp
21 auto_ptr<Singleton> Singleton::_instance;


3.用atexit替換smart pointer
C++并沒有規(guī)定不同編譯單元(translation unit,簡(jiǎn)單說就是一個(gè)可編譯的cpp文件)中static對(duì)象的初始化順序。如果一個(gè)程序中有多個(gè)Singleton對(duì)象,那么這些Singleton對(duì)象的析構(gòu)順序也將是任意的。很顯然,當(dāng)多個(gè)Singleton對(duì)象有依賴關(guān)系時(shí),smart pointer根本無法保證Singleton的析構(gòu)順序。

msdn中對(duì)atexit描述如下:

The atexit function is passed the address of a function (func) to be called when the program terminates normally. Successive calls to atexit create a register of functions that are executed in last-in, first-out (LIFO) order. The functions passed to atexit cannot take parameters. atexit  use the heap to hold the register of functions. Thus, the number of functions that can be registered is limited only by heap memory.

需要說明的是atexit并不比smart pointer好多少,LIFO的保證對(duì)于有復(fù)雜依賴關(guān)系的多個(gè)Singleton依然束手無力,但是用atexit替換smart pointer卻是必須的,它是設(shè)計(jì)完美Singleton的基礎(chǔ)。


#如果你疑惑atexit為什么還是不行,請(qǐng)考慮下面的情況:
NOTE:下面的情況在Modern C++ Design中叫做KDL(Keyboard,Display,Log)problem

某個(gè)程序中使用了如下3個(gè)Singleton:KeyboardDisplayLogKeyboardDisplay分別對(duì)應(yīng)于計(jì)算機(jī)的鍵盤和顯示器,Log用來記錄錯(cuò)誤信息。假設(shè)當(dāng)KeyboardDisplay的構(gòu)造函數(shù)和析構(gòu)函數(shù)出現(xiàn)錯(cuò)誤時(shí)會(huì)調(diào)用Log記錄錯(cuò)誤信息,并且構(gòu)造和析構(gòu)導(dǎo)致的任何錯(cuò)誤都會(huì)終止程序。

在程序啟動(dòng)時(shí),如果Keyboard構(gòu)造成功,Display構(gòu)造失敗,很顯然在Display的構(gòu)造函數(shù)中將會(huì)構(gòu)造Log而且失敗信息會(huì)被Log記錄,根據(jù)假設(shè)這時(shí)候程序準(zhǔn)備退出,atexit注冊(cè)的函數(shù)將會(huì)按LIFO的順序被調(diào)用。因?yàn)?span style="COLOR: #333399">Keyboard先于Log構(gòu)造,所以Log先于Keyboard析構(gòu),但是當(dāng)由于某種原因Keyboard在析構(gòu)時(shí)失敗,想要調(diào)用Log記錄錯(cuò)誤信息時(shí),Log早已被銷毀,則Log::Instance()將會(huì)導(dǎo)致未定義行為。

#atexit的嚴(yán)重問題:
從上面的例子可以看出,atexit和smart pointer相比僅僅是有LIFO的保證而已,這樣的保證貌似也不怎么有效,因?yàn)閍texit跟smart pointer一樣也無法解決KDL probleam

atexit由于LIFO帶來了另外的問題,看下面的代碼:

 1 #include <cstdlib>
 2 void  Bar() {
 3 
    ...
 4 
}
 5 void
 Foo() {
 6 
    std::atexit(Bar);
 7 
}
 8 int
 main() {
 9 
    std::atexit(Foo);
10     return 0
;
11 }

上面的小段代碼用atexit注冊(cè)了Foo,F(xiàn)oo調(diào)用了std::atexit(Bar)。當(dāng)程序退出時(shí),根據(jù)atexit的LIFO保證,Bar在Foo之后注冊(cè),因此Bar應(yīng)該在Foo之前調(diào)用,但是當(dāng)Bar注冊(cè)的時(shí)候Foo已經(jīng)調(diào)用了,Bar根本就沒有機(jī)會(huì)能夠在Foo之前調(diào)用。這明顯自相矛盾對(duì)吧,沒辦法,C++標(biāo)準(zhǔn)好像忽視了這一點(diǎn),因此如果類似代碼被調(diào)用,肯定不會(huì)有什么好的結(jié)果,好一點(diǎn)是resource leak,差一點(diǎn)估計(jì)程序就崩潰了!!!

atexit的這個(gè)問題跟Singleton有關(guān)系嗎?當(dāng)然有,如果在一個(gè)Singleton的析構(gòu)函數(shù)中調(diào)用atexit就會(huì)出現(xiàn)上述問題。即在KDL problem中,如果KeyboardDisplay都構(gòu)造成功,當(dāng)KeyboardDisplay任意一個(gè)析構(gòu)失敗時(shí),KeyboardDisplay在析構(gòu)函數(shù)中會(huì)構(gòu)造LogLog的構(gòu)造函數(shù)會(huì)間接調(diào)用atexit。oops!!!,可怕的未定義行為。

看到這里你一定對(duì)atexit相當(dāng)失望,貌似它帶來的好處多于壞處。但是請(qǐng)你相信,如果適當(dāng)設(shè)計(jì),atexit在后面的Singleton改造中會(huì)起到很重要的作用。

用atexit后的代碼:

 1 // Header file Singleton.h
 2 class  Singleton {
 3 public
:
 4     static Singleton& Instance() { // Unique point of access

 5         if (0 ==  _instance) {
 6             _instance = new
 Singleton();
 7             atexit(Destroy); // Register Destroy function

 8          }
 9         return *
_instance;
10 
    }
11     void
 DoSomething(){}
12 private
:
13     static void Destroy() { // Destroy the only instance

14         if ( _instance != 0  ) {
15 
            delete _instance;
16             _instance = 0
;
17 
        }
18 
    }
19     Singleton(){} // Prevent clients from creating a new Singleton

20     ~Singleton(){} // Prevent clients from deleting a Singleton
21     Singleton(const Singleton&); // Prevent clients from copying a Singleton
22     Singleton& operator=(const Singleton& );
23 private
:
24     static Singleton *_instance; // The one and only instance

25  };
26 

27 // Implementation file Singleton.cpp
28 Singleton* Singleton::_instance = 0;

你有沒有仔細(xì)考慮過Destroy中的_instance = 0;這一行代碼,上述代碼實(shí)際上實(shí)現(xiàn)的是不死鳥模式(The Phoenix Singleton),所謂不死鳥,就跟一輝一樣可以死而復(fù)生。上面的代碼可以解決本文最早提出的KDL problem,即如果Keyboard析構(gòu)失敗,雖然Log已經(jīng)析構(gòu),但是由于Destroy中的_instance = 0;這一行代碼,Log::Instance()將會(huì)創(chuàng)建一個(gè)新的Log對(duì)象,程序?qū)?huì)表現(xiàn)良好。當(dāng)然了,Phoenix Singleton僅能用于無狀態(tài)的Singleton,如果Log需要保存某些狀態(tài),Phoenix Singleton也不會(huì)帶來任何好處。你當(dāng)然可以用某些方法維持Phoenix Singleton的狀態(tài),但是在做之前先想想看是否值得,維持狀態(tài)可能會(huì)使Singleton變得特別復(fù)雜。

上面的Phoenix Singleton已經(jīng)可以滿足大部分需要,如果你的Singleton沒有涉及到多線程,多個(gè)Singleton之間也沒有依賴關(guān)系,你大可以放心使用。但是如果你用到多線程,或者你的Singleton關(guān)系如KDL般復(fù)雜,或者你覺得對(duì)每一個(gè)Singleton都敲同樣的代碼讓你厭煩。在后面幾篇會(huì)有一個(gè)多線程安全的,能夠解決多個(gè)Singleton依賴關(guān)系的,基于模板的Singleton實(shí)現(xiàn)。

posted on 2007-09-07 14:49 螞蟻終結(jié)者 閱讀(5039) 評(píng)論(12)  編輯 收藏 引用 所屬分類: Design Pattern

Feedback

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 15:04 5Element

不錯(cuò),期待下一篇。  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 15:53 DeathKnight

先贊一下你的文字排版 很漂亮  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1][未登錄] 2007-09-07 16:22 L

這個(gè)Singleton沒有加鎖,多線程下會(huì)有問題。  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 16:36 螞蟻終結(jié)者

@L
恩,其實(shí)還有很多問題,后面幾篇會(huì)解決  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 17:32 bgate

最起碼應(yīng)該寫成個(gè)模板類吧.  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 17:36 Minidx全文檢索

呵呵,的確是“非完美”的,不過支持一下~~~  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-07 19:29 螞蟻終結(jié)者

大家都沒有看到我最后一句話:
在后面幾篇會(huì)有一個(gè)多線程安全的,能夠解決多個(gè)Singleton依賴關(guān)系的,基于模板的Singleton實(shí)現(xiàn)。

由于篇幅比較長(zhǎng),所以分成好幾篇了,thanks!  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1][未登錄] 2007-09-07 20:49 楊粼波

看看Loki里面的實(shí)現(xiàn)。  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-08 09:10 螞蟻終結(jié)者

@楊粼波
Loki的我看過,不過感覺太復(fù)雜,也許有時(shí)候需要的只是最簡(jiǎn)單的  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-09 00:12 攀升

不知道能不能寫一個(gè)原型模式的文章,我最近想用  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-09 09:30 螞蟻終結(jié)者

@攀升
“原型模式”目前還沒有研究過,如果最近有時(shí)間的話可能會(huì)寫一篇  回復(fù)  更多評(píng)論   

# re: 非完美C++ Singleton實(shí)現(xiàn)[1] 2007-09-10 09:45 Uranus

謝謝,  回復(fù)  更多評(píng)論   

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            久久精品国产精品亚洲精品| 欧美另类69精品久久久久9999| 亚洲欧美日韩国产一区二区| 亚洲欧洲中文日韩久久av乱码| 亚洲国产专区| 亚洲美女av电影| 亚洲伊人网站| 久久婷婷国产综合尤物精品| 欧美不卡一卡二卡免费版| 欧美激情第二页| 日韩亚洲精品视频| 久久成人18免费网站| 玖玖综合伊人| 欧美日韩一区二区三区在线视频| 国产精品久久久99| 激情另类综合| 亚洲一区观看| 欧美成人a视频| 亚洲香蕉成视频在线观看 | 欧美一区二区三区四区高清| 久久久久久伊人| 最新国产の精品合集bt伙计| 亚洲作爱视频| 老巨人导航500精品| 国产精品九九久久久久久久| 一色屋精品亚洲香蕉网站| 一区二区三区 在线观看视频| 久久不射中文字幕| 亚洲最快最全在线视频| 一本大道久久a久久精品综合| 欧美怡红院视频| 欧美日韩高清在线一区| 久久久久在线| 久久精品一区| 亚洲另类视频| 久久人91精品久久久久久不卡| 亚洲人永久免费| 欧美永久精品| 国产精品一区在线观看你懂的| 亚洲高清久久网| 久久久久久久国产| 亚洲一区二区三区久久| 欧美日本韩国在线| 亚洲精品一二| 亚洲国产成人精品久久久国产成人一区 | 麻豆国产va免费精品高清在线| 亚洲一区二区免费| 欧美日韩午夜激情| 亚洲精品在线免费| 亚洲电影免费在线| 免费精品99久久国产综合精品| 国模私拍一区二区三区| 欧美呦呦网站| 性伦欧美刺激片在线观看| 国产精品综合av一区二区国产馆| 亚洲一区二区三区四区在线观看| 亚洲三级影院| 欧美日韩视频在线第一区| 一本久久青青| 一本久道久久综合婷婷鲸鱼| 欧美日韩色综合| 一区二区三区精密机械公司| 亚洲激情视频在线观看| 欧美aaa级| 日韩亚洲不卡在线| 日韩一级网站| 欧美午夜在线一二页| 亚洲女爱视频在线| 亚洲永久免费| 国模一区二区三区| 蜜臀99久久精品久久久久久软件| 久久久精品一品道一区| 狠狠色综合网| 亚洲国产精品成人久久综合一区 | 欧美va天堂va视频va在线| 亚洲激情成人在线| 日韩午夜视频在线观看| 国产欧美亚洲日本| 欧美激情四色| 欧美日韩综合视频| 久久经典综合| 牛牛精品成人免费视频| 亚洲午夜电影网| 性色av一区二区三区红粉影视| 国内不卡一区二区三区| 亚洲激情啪啪| 国产亚洲欧洲一区高清在线观看| 欧美国产精品劲爆| 亚洲激情国产精品| 在线一区观看| 一区二区三区在线看| 亚洲日本成人网| 国产亚洲精品bv在线观看| 欧美成人精品在线| 国产精品狼人久久影院观看方式| 久久精品视频亚洲| 欧美精品v国产精品v日韩精品| 午夜精品福利在线观看| 久久香蕉国产线看观看av| 99综合视频| 久久久精品国产免大香伊| 在线视频亚洲| 免费日韩精品中文字幕视频在线| 亚洲欧美日韩天堂| 欧美成人按摩| 另类av一区二区| 国产精品资源在线观看| 亚洲精品国产精品国自产在线| 国模精品娜娜一二三区| 亚洲一区999| 亚洲午夜激情免费视频| 美女国产一区| 久久综合999| 国产日韩欧美一区| 亚洲视频一区| 亚洲线精品一区二区三区八戒| 欧美18av| 女同一区二区| 又紧又大又爽精品一区二区| 亚洲自拍偷拍色片视频| 亚洲视频国产视频| 欧美日本免费一区二区三区| 亚洲电影有码| 91久久中文| 久热这里只精品99re8久| 久久久久高清| 国产一区亚洲| 久久久久久久精| 久久米奇亚洲| 狠狠色狠狠色综合日日小说| 欧美一二三区精品| 欧美伊人久久久久久久久影院 | 国产精品美女www爽爽爽| 亚洲精品影院| 亚洲一区二区三区精品在线观看 | 久久久久久**毛片大全| 久久国产精品72免费观看| 国产精品一区二区你懂得| 亚洲一区二区三区精品在线| 亚洲免费中文| 国产视频一区三区| 久久精品人人爽| 欧美成年人视频网站欧美| 在线观看日韩一区| 欧美国产欧美亚洲国产日韩mv天天看完整 | 国产精品老牛| 欧美夜福利tv在线| 欧美福利在线| 欧美成人一品| 欧美日韩成人在线视频| 亚洲三级网站| 午夜精品久久久久久久99水蜜桃| 国产精品区一区| 欧美伊久线香蕉线新在线| 美女国内精品自产拍在线播放| 在线日韩av片| 欧美日本三区| 欧美一区二区三区四区夜夜大片| 久久亚洲精品视频| 日韩一级精品| 国产欧美亚洲精品| 欧美大片网址| 亚洲女ⅴideoshd黑人| 蜜臀av性久久久久蜜臀aⅴ四虎| 亚洲精品一品区二品区三品区| 国产精品v亚洲精品v日韩精品 | 亚洲特级毛片| 国产揄拍国内精品对白| 欧美国产精品v| 欧美亚洲自偷自偷| 亚洲欧洲日韩女同| 欧美在线www| 亚洲裸体在线观看| 国产日韩欧美中文| 欧美精品日韩一本| 久久精品2019中文字幕| 亚洲精品女av网站| 久久精品观看| 国产精品99久久久久久久女警| 国产在线播放一区二区三区| 欧美日韩一区二区三区高清| 久久久久看片| 亚洲伊人久久综合| 亚洲乱码精品一二三四区日韩在线| 久久精品1区| 亚洲女同在线| 日韩午夜在线观看视频| 国产亚洲福利| 国产精品美女主播| 欧美日韩成人在线视频| 美女网站久久| 久久久人人人| 久久精品国产第一区二区三区最新章节 | 久久综合999| 欧美亚洲在线播放| 午夜欧美大尺度福利影院在线看| 亚洲精品中文字幕女同| 亚洲电影欧美电影有声小说| 国产一区视频观看| 国产一区 二区 三区一级|