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

Difference between Singleton implemention using pointer and using static object

本文关键字:实现 之间 区别 单例 对象 指针 静态      更新时间:2023-10-16

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

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

class Singleton
{
  private:
    static Singleton *p_inst;
    Singleton();
  public:
    static Singleton * instance()
    {
      if (!p_inst)
      {
        p_inst = new Singleton();
      }
      return p_inst;
    }
};

在这个

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
};

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

因为大多数描述Singleton AntiPattern的文章在试图在C 中安全实施时,并不完全理解所有隐藏的危险。做对了很难。

使用静态对象使用指针在实现单例类VS方面的实际优势是什么?

使用指针,带有new,但没有delete,可以确保对象永远不会被破坏,因此在其寿命结束后没有访问它的危险。结合"懒惰"的创建,第一次访问它,这可以确保所有访问权限均为有效对象。缺点是创建不是线程安全,并且该对象及其获得的任何资源均未在程序结束时发布。

使用本地静态对象,创建是支持C 11线程模型的任何编译器上的线程安全。此外,该对象将在程序结束时被破坏。但是,可以在对象破坏后访问该对象(例如,来自另一个静态对象的损坏器),这可能会导致讨厌的错误。

最好的选择是尽可能避免静态数据和全球可访问的数据。特别是,切勿使用Singleton Anti Pattern;它将全局静态数据与怪异的实例化限制相结合,这使得测试非常困难。

第二版(使用本地静态变量)具有显着优势。

它不需要使用自由商店,因此不会被检测到内存泄漏。它是线程安全(在C++11中)。它更短,更简单。

唯一的缺点是不可能使其处于Portable threadSafe(对于Pre-C 11编译器),并且它不会为您提供明确销毁Singleton实例的选项。

始终更喜欢第二个,但是第一个确实具有一些潜在的有趣优势: -

  • 清晰度 - 对指针为null的检查有效编译器在构造静态时在引擎盖下做什么对象。从"学习"的角度来看,了解方法中使用静态对象时发生了什么范围。

  • 懒惰分配 - 在第一种情况下,单例对象是堆分配。如果您的功能从未运行,则对象永远不会建造,永远不会消耗记忆。但是,在第二种情况下,内存由链接器分配以将对象保存在即使"施工"很懒惰。

第二个示例以" Meyers'Singleton"的名称知道,因为它首先在"有效的C "或"更有效的C "中发布。我不确定哪一个,但两者都是在"设计模式"之后出版的 - 因此,四人的帮派可能同样并不意识到他们的书写时的第二个模式。

另外,第一种方法是其他语言的标准性 - 您可以在Java或C#中进行第一种方法,但第二种方法是,因此来自不同背景的人可能是第一种更名的另一个原因。

在技术方面,您可以通过第一种方法来控制单身人士何时被摧毁,但这也可能会给您带来很多头痛。

第二个具有非确定性破坏。第一个,您可以控制何时删除指针,如果有的话。

当然,第一个构造不是线程安全,但可以使用boost::call_once(或std::call_once(如果有))进行

第二个结构足够常见在另一个线程使用它之前完成结构)。

如果破坏顺序没有问题,那么只要您的编译器将其保证为线程安全,就可以继续使用静态版本。

一个优势是您不必检查单身人是否已经实例化。

另一个是您不必担心去分配任何内存。

非本地静态怎么样?有人看到这个问题吗?

class Singleton
{
    static Singleton singleton;
    Singleton();
    // etc
public:
    static Singleton &Instance() { return singleton; }
};
Singleton Singleton::singleton;
// etc