简体   繁体   English

Java中的Singleton与C ++中的Singleton

[英]Singleton in java vs. Singleton in C++

In Java I can create a Singleton like this (as long as it doesn't throw as exception): 在Java中,我可以这样创建一个Singleton(只要它不作为异常抛出):

private static Singleton m_this = new Singleton();

This is very convenient because it's inherently thread safe. 这非常方便,因为它本质上是线程安全的。

Can I do something similar in C++? 我可以在C ++中做类似的事情吗?

One way of making a singleton with thread-safe initialization, guaranteed by the standard as of C++11. 一种使用线程安全初始化的单例方式,由C ++ 11的标准保证。 is: 是:

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

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

This is thread-safe, because local static variable initialization is thread-safe in C++11 . 这是线程安全的,因为本地静态变量初始化在C ++ 11中是线程安全的 The relevant standard document, N3485 , says in section 6.7.4: 相关标准文件N3485在6.7.4节中说:

such a variable is initialized the first time control passes through its declaration; 此类变量在控件第一次通过其声明时进行初始化; such a variable is considered initialized upon the completion of its initialization. 此类变量在初始化完成后即被初始化。 [...] If control enters the declaration concurrently while the variable is being initialized, the concurrent execution shall wait for completion of the initialization. [...]如果在初始化变量时控件同时输入声明,则并发执行应等待初始化完成。

with footnote: 带有脚注:

The implementation must not introduce any deadlock around execution of the initializer. 该实现不得在初始化程序的执行周围引入任何死锁。

You can abstract into a nice template base class with CRTP: 您可以使用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> {
  ...
};

If by Singleton , you mean a real singleton (which I'm not sure is the same you gave an example of, because you still could create a second Singleton instance and assign it to a different variable), the answer is yes . 如果用Singleton表示真正的 Singleton (我不确定您给出的示例是否相同),因为您仍然可以创建第二个Singleton实例并将其分配给其他变量),答案是yes You can create a singleton object using the factory pattern . 您可以使用工厂模式创建单例对象。

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

Instead of making a dedicated factory class, you could make getSingleton a static member function of singleton itself too. 您可以使getSingleton成为singleton本身的static成员函数,而不是创建专用的factory类。 Just remember to make the constructor private , so the user can't create multiple copies. 只需记住将构造函数设为private ,这样用户就不能创建多个副本。

Also, on top of answer given by Paweł Stawarz, I would add that copy constructor, move constructor (C++11), overloaded assignment operator and destructor should be private too. 另外,除了PawełStawarz给出的答案之外,我还要添加复制构造函数,move构造函数(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;
};

Being private, copy constructor, move constructor (C++11), overloaded assignment operator and destructor cannot be called from outside to clone an existing copy and also to destroy a copy just created. 作为私有的副本构造函数,移动构造函数(C ++ 11),重载的赋值运算符和析构函数,无法从外部调用以克隆现有副本并破坏刚刚创建的副本。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM