java中的Singleton与C ++中的Singleton

时间:2014-04-07 01:44:22

标签: java c++ singleton

在Java中我可以像这样创建一个Singleton(只要它不作为异常抛出):

private static Singleton m_this = new Singleton();

这非常方便,因为它本身就是线程安全的。

我可以在C ++中做类似的事情吗?

3 个答案:

答案 0 :(得分:3)

使用线程安全初始化制作单例的一种方法,由C ++ 11标准保证。是:

class SomeSingleton {
  public:
    static SomeSingleton& instance() {
      static SomeSingleton instance_;
      return instance_;
    }

  private:
  SomeSingleton() {
    ...
  }
};

这是线程安全的,因为local static variable initialization is thread-safe in C++11。相关的标准文档N3485在第6.7.4节中说明:

  

这样的变量在控件第一次通过其声明时被初始化;这样的变量在初始化完成后被认为是初始化的。 [...]如果控件在初始化变量时同时进入声明,则并发执行应等待初始化完成。

脚注:

  

实现不得在执行初始化程序时引入任何死锁。

您可以使用CRTP抽象为一个漂亮的模板基类:

//Singleton template definition
template <typename TDerived>
class Singleton {
  static_assert(is_base_of<Singleton, TDerived>::value, "Singleton: unexpected Derived template parameter");
  public:
    static TDerived& instance() {
      static TDerived instance_;
      return instance_;
    }

  protected:
  Singleton() {
  }
};

// SomeSingleton definition, using the Singleton template
class SomeSingleton : public Singleton<SomeSingleton> {
  ...
};

答案 1 :(得分:1)

如果通过 Singleton ,则表示真实 singleton(我不确定是否与您举例相同,因为您仍然可以创建第二个Singleton实例并将其分配给另一个变量),答案是。您可以使用工厂模式创建单个对象。

class factory;
class singleton{
   singleton(){}; // private constructor
   friend class factory;
};

class factory{
   private:
      static std::shared_ptr<singleton> object;

   public:
      static singleton& getSingleton(){
         if(object)
            return *object;
         object = new singleton;
         return *object;
      }
};

您可以将factory成为getSingleton成员函数,而不是专门的static课程。只记得创建构造函数singleton,这样用户就无法创建多个副本。

答案 2 :(得分:1)

此外,除了PawełStawarz给出的答案之外,我还要添加复制构造函数,移动构造函数(C ++ 11),重载赋值运算符和析构函数也应该是私有的。

class singleton{
   singleton(){}; // private constructor
   ~singleton(){}; // private destructor
   singleton(const singleton &src){}; // private copy constructor
   singleton(const singleton&& src){}; // private move constructor for C++11
   singleton& operator = (const singleton& src){return *this;} // private = operator
   friend class factory;
};

私有,复制构造函数,移动构造函数(C ++ 11),重载赋值运算符和析构函数不能从外部调用来克隆现有副本,也不能销毁刚刚创建的副本。