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

#ant

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

非完美C++ Singleton實現[1]

Singleton模式是一種非常簡單的設計模式,這種模式很常用也很容易被濫用。當你設計應用程序的時候,經常會遇到某些對象在整個程序的生命周期應該僅有一個實例的情況,比如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模式的定義很簡單,實現也有N多種,但是卻很難找到一個稱得上“完美”的。實現一個完美的Singleton比想象中要難的多,下面探索性的來實現一個非完美的。

1.典型實現
在C++中,Singleton模式的典型實現如下:

 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的構造函數設為private可以禁止客戶代碼直接創建Singleton對象,除此之外,Singleton的copy constructor和copy assignment operator都為private且僅有聲明沒有實現,禁止了客戶代碼拷貝Singleton對象。唯一可以創建Singleton對象的是Singleton自己的靜態成員函數Instance,這樣就在編譯器保證了Singleton實例的唯一性。上面這些是在C++中實現Singleton模式最基本的要點。

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

客戶代碼現在可以這樣使用Singleton:

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


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

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


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

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

 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++并沒有規定不同編譯單元(translation unit,簡單說就是一個可編譯的cpp文件)中static對象的初始化順序。如果一個程序中有多個Singleton對象,那么這些Singleton對象的析構順序也將是任意的。很顯然,當多個Singleton對象有依賴關系時,smart pointer根本無法保證Singleton的析構順序。

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的保證對于有復雜依賴關系的多個Singleton依然束手無力,但是用atexit替換smart pointer卻是必須的,它是設計完美Singleton的基礎。


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

某個程序中使用了如下3個Singleton:KeyboardDisplayLogKeyboardDisplay分別對應于計算機的鍵盤和顯示器,Log用來記錄錯誤信息。假設當KeyboardDisplay的構造函數和析構函數出現錯誤時會調用Log記錄錯誤信息,并且構造和析構導致的任何錯誤都會終止程序。

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

#atexit的嚴重問題:
從上面的例子可以看出,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,Foo調用了std::atexit(Bar)。當程序退出時,根據atexit的LIFO保證,Bar在Foo之后注冊,因此Bar應該在Foo之前調用,但是當Bar注冊的時候Foo已經調用了,Bar根本就沒有機會能夠在Foo之前調用。這明顯自相矛盾對吧,沒辦法,C++標準好像忽視了這一點,因此如果類似代碼被調用,肯定不會有什么好的結果,好一點是resource leak,差一點估計程序就崩潰了!!!

atexit的這個問題跟Singleton有關系嗎?當然有,如果在一個Singleton的析構函數中調用atexit就會出現上述問題。即在KDL problem中,如果KeyboardDisplay都構造成功,當KeyboardDisplay任意一個析構失敗時,KeyboardDisplay在析構函數中會構造LogLog的構造函數會間接調用atexit。oops!!!,可怕的未定義行為。

看到這里你一定對atexit相當失望,貌似它帶來的好處多于壞處。但是請你相信,如果適當設計,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;這一行代碼,上述代碼實際上實現的是不死鳥模式(The Phoenix Singleton),所謂不死鳥,就跟一輝一樣可以死而復生。上面的代碼可以解決本文最早提出的KDL problem,即如果Keyboard析構失敗,雖然Log已經析構,但是由于Destroy中的_instance = 0;這一行代碼,Log::Instance()將會創建一個新的Log對象,程序將會表現良好。當然了,Phoenix Singleton僅能用于無狀態的Singleton,如果Log需要保存某些狀態,Phoenix Singleton也不會帶來任何好處。你當然可以用某些方法維持Phoenix Singleton的狀態,但是在做之前先想想看是否值得,維持狀態可能會使Singleton變得特別復雜。

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

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

Feedback

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

不錯,期待下一篇。  回復  更多評論   

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

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

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

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

# re: 非完美C++ Singleton實現[1] 2007-09-07 16:36 螞蟻終結者

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

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

最起碼應該寫成個模板類吧.  回復  更多評論   

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

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

# re: 非完美C++ Singleton實現[1] 2007-09-07 19:29 螞蟻終結者

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

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

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

看看Loki里面的實現。  回復  更多評論   

# re: 非完美C++ Singleton實現[1] 2007-09-08 09:10 螞蟻終結者

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

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

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

# re: 非完美C++ Singleton實現[1] 2007-09-09 09:30 螞蟻終結者

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

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

謝謝,  回復  更多評論   


只有注冊用戶登錄后才能發表評論。
網站導航: 博客園   IT新聞   BlogJava   博問   Chat2DB   管理


青青草原综合久久大伊人导航_色综合久久天天综合_日日噜噜夜夜狠狠久久丁香五月_热久久这里只有精品
  • <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>
            国产一区二区三区丝袜| 国模吧视频一区| 亚洲一区二区在线免费观看| 亚洲网站视频| 国产视频久久久久久久| 欧美极品aⅴ影院| 一区二区三区鲁丝不卡| 久久夜色精品亚洲噜噜国产mv| 在线观看日韩av电影| 国产精品大片wwwwww| 久久久人成影片一区二区三区观看| 欧美风情在线观看| 欧美一区在线视频| 中文日韩电影网站| 亚洲欧洲在线看| 18成人免费观看视频| 国产九九视频一区二区三区| 欧美金8天国| 欧美aⅴ一区二区三区视频| 午夜精品视频在线| 亚洲午夜在线观看| 99视频热这里只有精品免费| 亚洲国产婷婷香蕉久久久久久| 久久精品99久久香蕉国产色戒| 亚洲黄色高清| 亚洲第一视频| 亚洲清纯自拍| 一区二区三区中文在线观看| 国产欧美一区二区三区沐欲 | 欧美一级视频精品观看| 99爱精品视频| 亚洲欧美日韩视频二区| 欧美亚洲一区二区三区| 久久本道综合色狠狠五月| 欧美在线二区| 欧美韩日一区二区三区| 亚洲精品国产欧美| 日韩一区二区精品视频| 午夜精品久久久久久久99热浪潮 | 久久久久久久久久久久久女国产乱| 久久狠狠亚洲综合| 欧美r片在线| 日韩视频在线一区二区| 亚洲香蕉在线观看| 久久久久一区| 欧美日韩亚洲在线| 国模吧视频一区| 亚洲私人黄色宅男| 久久夜色精品| 日韩午夜在线电影| 久久爱www| 欧美三区美女| 亚洲精品欧美激情| 蜜桃av综合| 亚洲在线观看视频| 欧美日韩国产美女| 亚洲高清资源| 美女日韩在线中文字幕| 午夜视频在线观看一区| 欧美日韩三级| 99精品热视频| 亚洲国产精品美女| 麻豆精品视频| 亚洲高清视频一区| 久久一二三国产| 欧美一级黄色录像| 国产精品影片在线观看| 亚洲欧美亚洲| 亚洲午夜极品| 国产亚洲精久久久久久| 久久精品国产99国产精品| 亚洲欧美激情精品一区二区| 国产精品进线69影院| 亚洲一区二区三区在线观看视频| 亚洲国产日韩在线| 欧美日韩一区二区在线播放| 99pao成人国产永久免费视频| 国产精品成人aaaaa网站| 在线视频成人| 亚洲美女视频在线观看| 国产免费一区二区三区香蕉精| 性欧美激情精品| 久久婷婷丁香| 99国产精品国产精品久久| 一本大道久久a久久精品综合| 国产精品久久久久久模特| 久久一区激情| 欧美视频精品在线| 老司机午夜精品视频| 欧美久久久久中文字幕| 久久国产精品久久久久久电车| 卡通动漫国产精品| 亚洲免费在线观看视频| 欧美怡红院视频| 一区二区三区蜜桃网| 欧美尤物巨大精品爽| 亚洲视频中文| 欧美/亚洲一区| 久久久999国产| 欧美午夜理伦三级在线观看| 免费久久99精品国产| 国产精品久久久久久久免费软件| 欧美国产精品日韩| 在线播放国产一区中文字幕剧情欧美 | 久久久久国产精品厨房| 国产精品亚洲欧美| 欧美与欧洲交xxxx免费观看| 一区二区成人精品| 欧美成年人视频| 蜜臀久久99精品久久久久久9 | 午夜精品剧场| 国产精品日韩在线观看| 久久精品免费播放| 亚洲国产精品悠悠久久琪琪| 在线不卡欧美| 欧美性一区二区| 久久婷婷av| 亚洲一区二区三区精品在线观看| 久久久久久国产精品mv| 一区二区三区精品视频| 久久激情一区| 最近看过的日韩成人| 国产精品久久久| 久久免费视频在线观看| 99re热这里只有精品免费视频| 亚洲午夜精品福利| 最新日韩精品| 国产一区二区三区高清播放| 久久亚洲一区二区| 欧美亚洲网站| 艳女tv在线观看国产一区| 麻豆精品在线观看| 午夜精品www| 亚洲精品视频啊美女在线直播| 国产精品永久在线| 国产精品日本一区二区| 欧美色图五月天| 欧美视频一区在线| 欧美日韩综合久久| 国产精品极品美女粉嫩高清在线 | 欧美国产在线视频| 欧美一区二区三区播放老司机| 亚洲国产日韩欧美| 国产日韩亚洲欧美综合| 欧美三级午夜理伦三级中视频| 久久九九国产精品怡红院| 一本色道**综合亚洲精品蜜桃冫| 美女日韩欧美| 久久激情婷婷| 亚洲综合色丁香婷婷六月图片| 在线日韩精品视频| 一区福利视频| 在线欧美影院| 一区二区三区在线免费播放| 国产一区二区三区在线观看视频| 欧美日韩午夜剧场| 国产精品久久一区主播| 国产精品高潮呻吟久久av无限| 欧美黄色影院| 欧美日韩一区二区三区在线| 欧美精品免费观看二区| 欧美日韩福利在线观看| 欧美精品一区二| 欧美日韩免费一区二区三区| 欧美日韩精品欧美日韩精品| 国产精品成人va在线观看| 国产精品免费区二区三区观看| 国产精品久久77777| 国产欧美亚洲视频| 伊人久久av导航| 亚洲精选一区| 久久精品国产欧美亚洲人人爽| 久久九九电影| 亚洲人成人一区二区在线观看| 日韩一区二区久久| 久久激情网站| 欧美午夜视频一区二区| 影音国产精品| 亚洲免费在线电影| 欧美国产三区| 亚洲免费视频网站| 老司机凹凸av亚洲导航| 国产日韩欧美不卡| 夜夜夜精品看看| 欧美成人国产一区二区| 性18欧美另类| 国产精品丝袜xxxxxxx| 亚洲手机在线| 亚洲精品一区在线观看| 欧美成人免费在线观看| 国产婷婷色一区二区三区在线 | 久久精品视频在线观看| 国产精品色午夜在线观看| 一本一本a久久| 亚洲黄色影院| 欧美精品情趣视频| 日韩亚洲不卡在线| 亚洲国产另类 国产精品国产免费| 久久久久久久久综合| 黄色成人在线免费|