将 shared_ptr 与单例一起使用有什么好处

What is the advantage of using shared_ptr with singleton

这里有两个单例,是什么让第一个更可取,因为两者都只会实例化相应 class 的一个实例:

第一个:

class SharedPointerSingleton  {
public:
      static std::shared_ptr< SharedPointerSingleton> getSingleton(
   {
      if( s_pSingleton== 0 ) s_pSingleton = std::shared_ptr< SharedPointerSingleton>(new SharedPointerSingleton());
      return s_pSingleton;
   }


private:
   SharedPointerSingleton(){};
   static std::shared_ptr< SharedPointerSingleton> s_pSingleton;
};

第二个:

class PointerSingleton  {
public:
      static  PointerSingleton * getSingleton(
   {
      if( pSingleton== 0 )  pSingleton =  new PointerSingleton ());
      return  pSingleton;
   }


private:
   PointerSingleton (){};
   static  PointerSingleton *  pSingleton;
};

两种实施方式各有利弊。第一个解决方案有使用 std::shared_ptr 的开销,这在某些情况下可能会很明显。第二种解决方案不会在程序结束时销毁单例对象。虽然内存会在程序生命周期结束时由 OS 释放,但不正确销毁 C++ 对象通常不是一个好习惯。它可能会直接或间接释放未被 OS 清除的资源,例如临时文件、共享内存等,通常的做法是在析构函数中释放资源。

程序结束时第二次泄漏(虽然 OS 应该 清理内存,但你缺少的析构函数调用可能是个问题)。这可能就是为什么有人在顶部添加了一个智能指针。

但是,两个版本都已损坏,容易受到初始化顺序问题的影响。

相反,"proper"产生单例的方法是这样的:

class SharedPointerSingleton
{
   SharedPointerSingleton() = default;

public:
   static SharedPointerSingleton& getSingleton(
   {
      static SharedPointerSingleton instance;
      return instance;
   }
};

这种方法是安全的,没有智能指针或动态分配的开销。现在这个对象在你第一次请求它的时候就被精确地构建了,这要好得多(除非你想要它在main之前发生......但是你仍然可以在命名空间实例化它如果您愿意,可以通过调用此函数进行范围!)。