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

#ant

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

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

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

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

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

1.典型實現(xiàn)
在C++中,Singleton模式的典型實現(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對象,除此之外,Singleton的copy constructor和copy assignment operator都為private且僅有聲明沒有實現(xiàn),禁止了客戶代碼拷貝Singleton對象。唯一可以創(chuàng)建Singleton對象的是Singleton自己的靜態(tài)成員函數(shù)Instance,這樣就在編譯器保證了Singleton實例的唯一性。上面這些是在C++中實現(xiàn)Singleton模式最基本的要點(diǎn)。

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

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

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


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

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


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

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

 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,簡單說就是一個可編譯的cpp文件)中static對象的初始化順序。如果一個程序中有多個Singleton對象,那么這些Singleton對象的析構(gòu)順序也將是任意的。很顯然,當(dāng)多個Singleton對象有依賴關(guān)系時,smart pointer根本無法保證Singleton的析構(gòu)順序。

msdn中對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的保證對于有復(fù)雜依賴關(guān)系的多個Singleton依然束手無力,但是用atexit替換smart pointer卻是必須的,它是設(shè)計完美Singleton的基礎(chǔ)。


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

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

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

#atexit的嚴(yán)重問題:
從上面的例子可以看出,atexit和smart pointer相比僅僅是有LIFO的保證而已,這樣的保證貌似也不怎么有效,因為atexit跟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注冊了Foo,F(xiàn)oo調(diào)用了std::atexit(Bar)。當(dāng)程序退出時,根據(jù)atexit的LIFO保證,Bar在Foo之后注冊,因此Bar應(yīng)該在Foo之前調(diào)用,但是當(dāng)Bar注冊的時候Foo已經(jīng)調(diào)用了,Bar根本就沒有機(jī)會能夠在Foo之前調(diào)用。這明顯自相矛盾對吧,沒辦法,C++標(biāo)準(zhǔn)好像忽視了這一點(diǎn),因此如果類似代碼被調(diào)用,肯定不會有什么好的結(jié)果,好一點(diǎn)是resource leak,差一點(diǎn)估計程序就崩潰了!!!

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

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

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

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

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

Feedback

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

不錯,期待下一篇。  回復(fù)  更多評論   

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

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

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

這個Singleton沒有加鎖,多線程下會有問題。  回復(fù)  更多評論   

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            亚洲免费不卡| 亚洲免费网址| 亚洲国产精品久久久久婷婷884| 午夜精品久久久久久 | 欧美二区在线播放| 欧美不卡高清| 日韩视频永久免费观看| 亚洲精品久久久久久久久久久久久| 欧美精品在线一区二区| 亚洲一区二区伦理| 欧美在线资源| 亚洲精品一品区二品区三品区| 亚洲日本中文字幕区| 亚洲精一区二区三区| 国产亚洲一本大道中文在线| 久久免费视频在线观看| 欧美激情亚洲国产| 欧美在线视频播放| 欧美大片国产精品| 欧美在线视频网站| 欧美国产第一页| 久久精品毛片| 欧美日本一区| 老司机精品福利视频| 欧美三级乱人伦电影| 久久久精彩视频| 欧美三级特黄| 欧美电影美腿模特1979在线看| 国产精品v日韩精品| 欧美激情a∨在线视频播放| 国产精品成人观看视频免费| 欧美高清视频一区| 国产日本欧洲亚洲| 日韩一区二区免费看| 亚洲国产清纯| 香蕉成人久久| 亚洲欧美中日韩| 欧美激情精品久久久久久| 久久久91精品国产一区二区三区| 欧美欧美全黄| 欧美 日韩 国产 一区| 国产精品尤物| 一区二区三区 在线观看视| 亚洲高清视频中文字幕| 午夜精品一区二区三区在线视 | 国产一区二区三区丝袜| 夜夜嗨av色综合久久久综合网| 亚洲国产日韩在线一区模特| 亚洲欧美自拍偷拍| 性久久久久久久| 欧美日韩国产a| 亚洲福利一区| 91久久精品国产91性色tv| 久久精品日产第一区二区| 久久精品国产综合| 国产欧美欧美| 先锋影音一区二区三区| 久久国产精品99久久久久久老狼| 欧美特黄一级大片| 在线亚洲激情| 亚洲一区在线播放| 欧美体内谢she精2性欧美| 亚洲人成在线免费观看| 在线亚洲观看| 国产精品久久久久77777| 一本色道久久综合精品竹菊 | 国内精品视频666| 欧美尤物一区| 免费成人黄色av| 91久久久亚洲精品| 欧美日韩成人综合天天影院| 亚洲精品午夜| 午夜欧美不卡精品aaaaa| 国产视频一区在线观看| 欧美诱惑福利视频| 免费日韩成人| 一区二区精品国产| 欧美亚洲综合另类| 蜜臀va亚洲va欧美va天堂| 亚洲国产精品嫩草影院| 欧美久久久久久久| 一区二区三区久久| 久久综合精品一区| 99re66热这里只有精品3直播| 欧美性猛交一区二区三区精品| 亚洲一区二区三区四区在线观看 | 欧美一区二区三区的| 国产一区二区三区四区三区四| 蜜桃视频一区| 这里是久久伊人| 久久人91精品久久久久久不卡| 91久久久国产精品| 国产精品毛片va一区二区三区| 欧美有码在线视频| 亚洲人成啪啪网站| 久久久蜜桃精品| 亚洲系列中文字幕| 国语自产精品视频在线看一大j8| 欧美成人69av| 亚洲欧美日本国产专区一区| 欧美成人一区在线| 午夜天堂精品久久久久| 亚洲国产精品高清久久久| 欧美日韩在线免费视频| 久久精品亚洲国产奇米99| 亚洲三级视频在线观看| 久久久久久伊人| 亚洲影院在线| 日韩亚洲不卡在线| 伊人夜夜躁av伊人久久| 国产精品视频yy9299一区| 欧美bbbxxxxx| 久久久夜夜夜| 亚洲欧美国产另类| 日韩一级二级三级| 欧美福利电影网| 久久亚洲一区二区| 午夜精品福利在线观看| 一本久道久久久| 在线色欧美三级视频| 国产欧美精品日韩区二区麻豆天美| 免费人成精品欧美精品| 性欧美在线看片a免费观看| 99精品国产一区二区青青牛奶| 欧美大片一区二区三区| 久久精品二区| 久久国产高清| 欧美亚洲一区二区在线观看| 中文在线资源观看网站视频免费不卡| 亚洲福利一区| 亚洲国产精品一区二区久| 韩国亚洲精品| 国产一区二区无遮挡| 国产免费观看久久| 国产欧美日韩综合一区在线观看| 欧美日韩综合| 欧美日韩1234| 欧美色网一区二区| 欧美日韩一区二区欧美激情| 欧美韩国在线| 欧美日本网站| 国产精品啊啊啊| 国产精品自拍在线| 国产欧美 在线欧美| 国产乱人伦精品一区二区| 国产欧美一区二区精品仙草咪 | 亚洲人在线视频| 这里是久久伊人| 一本色道久久88精品综合| 欧美福利视频在线| 美女诱惑一区| 米奇777在线欧美播放| 欧美高清一区二区| 亚洲国产婷婷香蕉久久久久久99| 欧美大片在线看免费观看| 欧美黄色大片网站| 亚洲国产精品嫩草影院| 99精品视频一区| 午夜视频在线观看一区二区三区| 亚洲欧美一区二区三区久久 | 亚洲一区亚洲二区| 亚洲一品av免费观看| 亚洲欧美国产日韩天堂区| 欧美夜福利tv在线| 你懂的视频欧美| 欧美日韩精选| 国产一区深夜福利| 136国产福利精品导航| 99国产精品久久久久老师| 亚洲综合三区| 免费看成人av| 亚洲深夜av| 久久综合网络一区二区| 欧美日韩亚洲在线| 狠狠综合久久| 一区二区av在线| 美女免费视频一区| 日韩视频在线一区二区三区| 午夜亚洲福利| 欧美日在线观看| 在线播放日韩| 午夜视频久久久| 亚洲经典一区| 久久精品综合网| 国产精品福利在线| 亚洲三级网站| 久久久夜精品| 亚洲午夜在线视频| 欧美不卡激情三级在线观看| 国产偷自视频区视频一区二区| 99re亚洲国产精品| 免费欧美日韩国产三级电影| 中国av一区| 欧美日产一区二区三区在线观看| 韩国一区二区在线观看| 亚洲欧美精品中文字幕在线| 亚洲美女一区| 六月婷婷一区| 激情久久久久久久久久久久久久久久 | 午夜一级久久|