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

#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模式最基本的要點。

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)在進程結(jié)束的時候都會對內(nèi)存很好的進行回收。比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是什么,花點時間熟悉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)于計算機的鍵盤和顯示器,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根本就沒有機會能夠在Foo之前調(diào)用。這明顯自相矛盾對吧,沒辦法,C++標(biāo)準(zhǔn)好像忽視了這一點,因此如果類似代碼被調(diào)用,肯定不會有什么好的結(jié)果,好一點是resource leak,差一點估計程序就崩潰了!!!

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;

你有沒有仔細考慮過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>
            久久久久国产一区二区三区四区| 久久久91精品国产一区二区精品| 久久婷婷亚洲| 国产嫩草影院久久久久| 欧美成人69av| 亚洲黄色小视频| 欧美精品在欧美一区二区少妇| 亚洲国产天堂久久综合网| 亚洲一区中文| 久久精品99国产精品| 激情一区二区三区| 午夜精品www| 国产精品成人播放| 亚久久调教视频| 亚洲高清在线观看一区| 亚洲美女黄色片| 国产精品久久999| 国产精品一区在线播放| 欧美成人高清视频| 欧美成人在线免费观看| 欧美一级在线视频| 国产日韩精品久久| 狠狠色狠狠色综合日日tαg| 欧美黄色aaaa| 亚洲欧美日韩视频二区| 亚洲国产乱码最新视频| 亚洲美女视频在线免费观看| 久久久久久久久伊人| 欧美大片在线影院| 99精品国产在热久久| 欧美国产日产韩国视频| 久久精品国产久精国产思思| 模特精品裸拍一区| 日韩亚洲一区在线播放| 久久国产综合精品| 亚洲综合99| 亚洲久久成人| 亚洲福利免费| 欧美在线播放| 亚洲精品欧美精品| 欧美一区二区私人影院日本| 欧美国产另类| 狠狠操狠狠色综合网| 一区二区日韩免费看| 在线精品在线| 黄色国产精品一区二区三区| 日韩视频在线你懂得| 最新中文字幕亚洲| 136国产福利精品导航网址| 一区二区三区四区五区在线 | 亚洲欧美久久久| 欧美电影打屁股sp| 欧美电影在线观看| 国产亚洲精品久久久久婷婷瑜伽 | 久久久久久久91| 国产精品揄拍500视频| 99亚洲精品| 亚洲天堂网站在线观看视频| 在线一区二区三区四区| 久久免费黄色| 欧美国产精品专区| 欧美一区二区精美| 国产精品一区二区你懂得| 国产精品欧美日韩| 欧美精品久久一区| 欧美日韩国产综合视频在线观看中文| 久久综合网色—综合色88| 久久精品夜色噜噜亚洲aⅴ| 久久视频在线视频| 欧美人与禽猛交乱配视频| 影音国产精品| 99成人在线| 亚洲国产导航| 欧美大片91| 日韩视频在线播放| 亚洲国产一区二区视频| 欧美精品一区二区三区在线看午夜| 亚洲国产精彩中文乱码av在线播放| 亚洲欧洲日产国产网站| 欧美高清在线一区二区| 免费成人黄色片| 欧美四级在线观看| 国产一区二区三区在线观看免费 | 亚洲欧美久久| 国产专区精品视频| 一级日韩一区在线观看| 亚洲免费观看| 国产精品jizz在线观看美国| 激情小说另类小说亚洲欧美 | 日韩亚洲欧美一区| 国产精品家庭影院| 快播亚洲色图| 亚洲调教视频在线观看| 老司机凹凸av亚洲导航| 亚洲欧洲精品一区二区三区不卡 | 极品尤物av久久免费看| 亚洲二区三区四区| 欧美午夜免费电影| 久久婷婷成人综合色| 老司机免费视频一区二区| 日韩网站在线看片你懂的| 中文在线一区| 欧美日本免费| 久久超碰97人人做人人爱| 99国产精品99久久久久久粉嫩| 欧美网站在线| 欧美成人一区在线| 国产精品久久久久一区二区三区| 亚洲九九九在线观看| 亚洲欧美日韩天堂| 欧美大成色www永久网站婷| 欧美专区18| 国产精品a级| 亚洲日本欧美| 欧美日韩国产一区| 蜜臀av性久久久久蜜臀aⅴ四虎| 久久精品国产免费看久久精品| 亚洲美女精品一区| 玖玖玖免费嫩草在线影院一区| 午夜精品国产更新| 欧美日韩久久| 亚洲图片欧美午夜| 免费成人在线观看视频| 久久久九九九九| 国产精品毛片大码女人| 最新日韩中文字幕| 国产精品第十页| 欧美国内亚洲| 怡红院精品视频| 亚洲欧美在线磁力| 一本色道久久综合一区| 久久精品视频网| 亚洲在线视频网站| 亚洲毛片播放| 先锋影音久久久| 欧美一区二区三区在线观看视频| 国产模特精品视频久久久久| 亚洲在线观看免费视频| 国产在线观看一区| 一本大道久久a久久精品综合| 玖玖综合伊人| 一二三区精品| 亚洲综合激情| 国产日韩精品视频一区二区三区| 亚洲午夜av电影| 国产主播在线一区| 亚洲精品你懂的| 欧美日韩精品免费看| 99re热精品| 国产精品进线69影院| 久久综合影音| 欧美日韩情趣电影| 久久男女视频| 在线精品视频一区二区| 亚洲乱码国产乱码精品精| 国产伦精品一区二区三区高清| 免费亚洲视频| 欧美色图五月天| 亚洲欧美在线播放| 日韩视频在线一区二区三区| 校园春色国产精品| 欧美一区在线直播| 激情久久一区| 免费毛片一区二区三区久久久| 久久免费观看视频| 中文精品一区二区三区| 久久精品一区中文字幕| 亚洲精品一区二区在线观看| 欧美日韩免费在线| 欧美第一黄色网| 国产综合精品| 亚洲一区二区视频| 欧美黄色aaaa| 精品999网站| 亚洲免费在线精品一区| 欧美三日本三级少妇三99| 亚洲欧美高清| 亚洲免费影视第一页| 亚洲国产1区| 欧美国产精品| 亚洲综合三区| 亚洲一区二区三区在线看| 美女视频一区免费观看| 亚洲国产精品成人一区二区 | 亚洲欧美中文另类| 欧美色欧美亚洲高清在线视频| 久久久午夜精品| 久久亚洲欧美| 国产拍揄自揄精品视频麻豆| 99热在这里有精品免费| 欧美精品一区二| 欧美激情一区二区三区在线视频观看 | 亚洲一区自拍| 最新亚洲激情| 99国产精品| 欧美激情国产高清| 亚洲国产精品毛片| 欧美国产日韩在线观看| 亚洲激情电影在线| 欧美另类videos死尸|