[英]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.