C++中的單例模式


轉自:http://blog.csdn.net/hackbuteer1/article/details/7460019 程序員

單例模式是一種經常使用的軟件設計模式。在它的核心結構中只包含一個被稱爲單例類的特殊類。經過單例模式能夠保證系統中一個類只有一個實例並且該實例易於外界訪問,從而方便對實例個數的控制並節約系統資源。若是但願在系統中某個類的對象只能存在一個,單例模式是最好的解決方案。顯然單例模式的要點有三個:一是某個類只能有一個實例;二是它必須自行建立這個實例;三是它必須自行向整個系統提供這個實例;設計模式

 單例模式其意圖是保證一個類僅有一個實例,並提供一個訪問它的全局訪問點,該實例被全部程序模塊共享。ide

《設計模式》一書中給出了一種很不錯的實現,定義一個單例類,使用類的私有靜態指針變量指向類的惟一實例,並用一個公有的靜態方法獲取該實例。函數


class CSingleton
{private:
   CSingleton()   //構造函數是私有的  
     {
   }  
    static CSingleton *m_pInstance;
    public:    
    static CSingleton * GetInstance()
   {      
     if(m_pInstance == NULL)  //判斷是否第一次調用
           
           m_pInstance = new CSingleton();    
               return m_pInstance;
   }
};

GetInstance()使用懶惰初始化,也就是說它的返回值是當這個函數首次被訪問時被建立的。spa

 上述代碼可能存在的問題:操作系統

m_pInstance指向的空間何時釋放呢?更嚴重的問題是,該實例的析構函數何時執行?.net

一個妥善的方法是讓這個類本身知道在合適的時候把本身刪除,或者說把刪除本身的操做掛在操做系統中的某個合適的點上,使其在恰當的時候被自動執行。
咱們知道,程序在結束的時候,系統會自動析構全部的全局變量。事實上,系統也會析構全部的類的靜態成員變量,就像這些靜態成員也是全局變量同樣。利用這個特徵,咱們能夠在單例類中定義一個靜態成員變量,而它的惟一工做就是在析構函數中刪除單例類的實例
設計

class CSingleton
{private:
   CSingleton()
   {
   }    
   static CSingleton *m_pInstance;  
    class CGarbo   //它的惟一工做就是在析構函數中刪除CSingleton的實例  
      {    
      public:      
       ~CGarbo()
       {        
          if(CSingleton::m_pInstance)
               delete CSingleton::m_pInstance;
       }
   };    
   static CGarbo Garbo;  //定義一個靜態成員變量,程序結束時,系統會自動調用它的析構函數public:    static CSingleton * GetInstance()
   {        if(m_pInstance == NULL)  //判斷是否第一次調用
           m_pInstance = new CSingleton();        return m_pInstance;
   }
};

類CGarbo被定義爲CSingleton的私有內嵌類,以防該類被在其餘地方濫用。
程序運行結束時,系統會調用CSingleton的靜態成員Garbo的析構函數,該析構函數會刪除單例的惟一實例
指針

添加一個類的靜態對象,老是讓人不太滿意,因此有人用以下方法來從新實現單例和解決它相應的問題,代碼以下:orm

class CSingleton
{private:
   CSingleton()   //構造函數是私有的    {
   }
   public:
      static CSingleton & GetInstance()
   {        static CSingleton instance;   //局部靜態變量
       return instance;
   }
};

使用局部靜態變量,很是強大的方法,徹底實現了單例的特性,並且代碼量更少,也不用擔憂單例銷燬的問題。 但使用此種方法也會出現問題,當以下方法使用單例時問題來了, Singleton singleton = Singleton :: GetInstance(); 這麼作就出現了一個類拷貝的問題,這就違背了單例的特性。產生這個問題緣由在於:編譯器會爲類生成一個默認的構造函數,來支持類的拷貝。

最後沒有辦法,咱們要禁止類拷貝和類賦值,禁止程序員用這種方式來使用單例,函數的代碼改成以下:

class CSingleton
{private:
   CSingleton()   //構造函數是私有的    {
   }
   public:  
    static CSingleton * GetInstance()
   {        static CSingleton instance;   //局部靜態變量
       return &instance;
   }
};

能夠顯示的聲明類拷貝的構造函數,和重載 = 操做符,新的單例類以下:(個人理解:不將instance設爲private static成員變量,是由於不清楚它何時被初始化 )

class CSingleton

{private:    CSingleton()   //構造函數是私有的        {    }    CSingleton(const CSingleton &);    CSingleton & operator = (const CSingleton &);    public:        static CSingleton & GetInstance()    {            static CSingleton instance;   //局部靜態變量,相比較指針指向的堆上對象,不用擔憂銷燬問題        return instance;    }};
相關文章
相關標籤/搜索