2012-07-20 54 views
2

我通常實現Singleton模式是這樣的:C++不同的單實現

class Singleton 
{ 
    public: 
     virtual ~Singleton() {} 

     static Singleton& GetInstance() 
     { 
      static Singleton instance; 
      return instance; 
     } 

    private: 
     Singleton(); 
     Singleton(const Singleton&); 
     Singleton& operator=(const Singleton&); 
} 

最近,我遇到了這個實施,這是稍有不同:

class Singleton 
{ 
    public: 
     Singleton(); 
     virtual ~Singleton() {} 

     static Singleton& GetInstance() 
     { 
      return instance; 
     } 

    private: 
     Singleton(const Singleton&); 
     Singleton& operator=(const Singleton&); 

     static Singleton instance; 
} 

Singleton Singleton::instance; 

哪種實現更好?

不使構造函數私有(第二個實現)是否危險?

謝謝。

回答

3

有差別。在第一種情況下,instance在函數的第一次調用時被初始化。在第二種情況下,它在程序啓動時被初始化。

如果你犯了一個public構造 - 它不是一個singleton,因爲它可以由任何人

1

第二種方案是錯誤創建。默認的構造函數應該是私有的。事實上,它本身並不是單一的。除此之外,@Andrew和@Brady答案中提到了這些實現之間的差異。

3

行爲的主要區別會來,如果你嘗試另一個命名空間級別的變量或類的靜態成員的初始化過程中使用的單。在第一種情況下,因爲在第一次函數調用期間按需創建實際對象,所以在建立期間行爲將被很好地定義。在第二種情況下,由於來自不同翻譯單元的靜態對象的初始化的相對順序未定義,所有投注都關閉。

另外請注意,雖然第一個在施工期間是安全的,它可能不會在銷燬期間。也就是說,如果具有靜態存儲持續時間的對象在構建過程中不使用單例,則可以在單例實例之前對其進行初始化。破壞順序與建造順序相反,在這種情況下,單身人士將在另一個物體之前銷燬。如果該對象在其析構函數中使用單例,則會導致未定義的行爲。

4

我不需要重複關於在其他答案中做出的單例的懶惰構造的好處。

讓我補充一點:

public: 
    Singleton(); 
    virtual ~Singleton() {} 

這個特殊類的設計者覺得有必要讓:

從這個 Singleton
  • 推導,說派生類被稱爲DerSingleton
  • DerSingleton可以具有可以刪除的實例指針Singleton(所以DerSingleton不是單)

DerSingleton任何實例也是通過定義一個Singleton實例,因此它遵循如果DerSingleton被實例化,Singleton不是單例。

所以這個設計斷言兩兩件事:

  • 這個類是單
  • 這個類是單身