使用指针和使用静态对象的Singleton实现之间的区别

Ano*_*non 24 c++ singleton design-patterns

编辑:对不起,我的问题不明确,为什么书籍/文章更喜欢实施#1而不是实施#2?

使用指针实现Singleton类与使用静态对象的实际优势是什么?为什么大多数书都喜欢这个

class Singleton
{
  private:

    static Singleton *p_inst;
    Singleton();

  public:

    static Singleton * instance()
    {
      if (!p_inst)
      {
        p_inst = new Singleton();
      }

      return p_inst;
    }
};
Run Code Online (Sandbox Code Playgroud)

在此

class Singleton
{
  public:
    static Singleton& Instance()
    {
        static Singleton inst;
        return inst;
    }

  protected:
    Singleton(); // Prevent construction
    Singleton(const Singleton&); // Prevent construction by copying
    Singleton& operator=(const Singleton&); // Prevent assignment
    ~Singleton(); // Prevent unwanted destruction
};
Run Code Online (Sandbox Code Playgroud)

Mik*_*our 17

为什么书籍/文章更喜欢实施#1而不是实施#2?

因为大多数描述Singleton反模式的文章在尝试在C++中安全地实现它时并不完全理解所有隐藏的危险.做到这一点非常困难.

使用指针实现Singleton类与使用静态对象的实际优势是什么?

使用指针new但是没有delete,确保永远不会销毁该对象,因此在其生命周期结束后不存在访问它的危险.结合"懒惰"创建,第一次访问它,这保证了所有访问都是有效的对象.缺点是创建不是线程安全的,并且它获取的对象和任何资源不会在程序结束时释放.

使用本地静态对象,在任何支持C++ 11线程模型的编译器上创建都是线程安全的.此外,该对象将在程序结束时被销毁.但是,可以在破坏后访问对象(例如,从另一个静态对象的析构函数),这可能会导致令人讨厌的错误.

最好的选择是尽可能避免静态数据和全局可访问的数据.特别是,永远不要使用Singleton反模式; 它将全局静态数据与奇怪的实例化限制相结合,使得测试变得不必要.

  • +1用于调用Singleton和反模式.我不一定同意"从不使用",但肯定"很少使用". (2认同)

Man*_*rse 8

第二个版本(使用本地静态变量)具有显着的优点.

它不需要使用免费存储,因此不会被检测为内存泄漏.它是线程安全的(in C++11).它更短更简单.

唯一的缺点是它不可能使其成为线程安全(对于前C++ 11编译器),并且它不会为您提供显式销毁单例实例的选项.


Iva*_*iev 5

第二个示例被称为“Meyers' Singleton”,因为它首先在“Effective C++”或“More Effect C++”中发布。我不确定是哪一个,但两者都是在“设计模式”之后出版的 - 所以四人帮在写书时可能还没有意识到第二种模式。

此外,第一种方法对于其他语言来说更为标准 - 您可以使用 Java 或 C# 执行第一种方法,但不能使用第二种方法,因此来自不同背景的人可能是第一种方法更出名的另一个原因。

从技术角度来说,第一种方法可以控制单例何时被销毁,但这也会给你带来很多麻烦。