2012-07-20 60 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不是单例。

所以这个设计断言两两件事:

  • 这个类是单
  • 这个类是单身