http://blog.csdn.net/windboyzsj/article/details/2790485
最近接觸的一個項目要用到單件模式,我像往常一樣噠噠(敲擊鍵盤ing)一個單件模式的典型結構很快就出現在我的面前:
- class Singleton
- {
- public:
- ~Singleton(){}
- static Singleton* Instance()
- {
- if (_instance == NULL)
- {
- _instance = new Singleton();
- }
- return _instance;
- }
- private:
- Singleton(){}
- static Singleton* _instance;
- };
- Singleton* Singleton::_instance = NULL;
不知道為什么,這次突然覺得new這個單詞太耀眼了,熟悉c++的程序員都知道,有new就離不開delete,既然單件模式共用一個實例,那么這個實例什么時候釋放呢。帶著好奇我在它的析構函數加了個打印語句,但由于new操作是在堆里分配內存,估計它的析構函數不會被調用,而試驗結果確實如此。這樣一來那單件模式的析構函數不是完全廢了嗎,如果這個單件類還有指針成員用new分配了空間那又應該在哪里釋放?單件的實例又應該如何釋放。當然,我們可以在程序退出時通過 delete Singleton::Instance(); 來釋放內存并觸發析構函數。但這樣一來,寫好的類給別人用時就要叮囑別人,用完后一定要釋放- - !,再說別人不一定記得...有沒有一種機制讓單件模式自動釋放?百度,google很久,發現關注這個問題的寥寥無幾,但還是給我找到了一篇文章讓我再次領略C++的靈活。按此文章大概把代碼修改如下;
- class Singleton
- {
- public:
- ~Singleton(){}
- static Singleton* Instance()
- {
- if (_instance == NULL)
- {
- _instance = new Singleton();
- }
- return _instance;
- }
- private:
- Singleton(){}
- static Singleton* _instance;
- class Cleaner
- {
- public:
- Cleaner(){}
- ~Cleaner()
- {
- if(Singleton::Instance())
- delete Singleton::Instance();
- }
- };
- static Cleaner clr;
- };
- Singleton* Singleton::_instance = NULL;
事先聲明我用VC6.0編譯上面的代碼(當然我有加一些測試代碼)發現,clr并沒有實例化,當然也就是沒有析構了,暫時不清楚為什么,但這里的設計卻是很值得品味。它通過一個內嵌類和一個靜態成員來實現了自動釋放的機制,相當于為單件加了個垃圾回收器。整個設計最巧妙的地方在于static Cleaner clr;這個聲明,由于是靜態成員,系統會在棧里分配內存,回收工作也就由系統自動完成了。這個思路另我想起了通過靜態變量來實現類的靜態構造函數,他們都有異曲同工之處。至于私有的內嵌類主要是防止單件類的專用垃圾筒被打擾...
雖然上面代碼沒有達到目的,但根據他的思路,可以做一下調整,把Cleaner的實例化延遲,下面貼出整個測試代碼,一下代碼在VC6編譯通過。
- #include <iostream.h>
- class Singleton
- {
- public:
- ~Singleton(){cout<<"singleton deconstruct"<<endl;}
- static Singleton* Instance()
- {
- if (_instance == NULL)
- {
- _instance = new Singleton();
- static Cleaner cl; //延遲到這里
- }
- return _instance;
- }
- void Print(char* str)
- {
- cout<<"singleton print:"<<str<<endl;
- }
- private:
- Singleton(){cout<<"singleton construct"<<endl;}
- static Singleton* _instance;
- class Cleaner
- {
- public:
- Cleaner(){cout<<"cleaner construct"<<endl;}
- ~Cleaner()
- {
- cout<<"cleaner deconstruct"<<endl;
- if(Singleton::Instance())
- delete Singleton::Instance();
- }
- };
- };
- Singleton* Singleton::_instance = NULL;
- int main(int argc, char* argv[])
- {
- Singleton::Instance()->Print("print 1");
- Singleton::Instance()->Print("print 2");
- return 0;
- }
![]() |
不含病毒。www.avast.com |