Reputation: 2825
In Java I can create a Singleton like this (as long as it doesn't throw as exception):
private static Singleton m_this = new Singleton();
This is very convenient because it's inherently thread safe.
Can I do something similar in C++?
Upvotes: 2
Views: 400
Reputation: 7128
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.
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.
Upvotes: 1
Reputation: 5118
One way of making a singleton with thread-safe initialization, guaranteed by the standard as of 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. The relevant standard document, N3485, says in section 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:
//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> {
...
};
Upvotes: 3
Reputation: 4012
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. 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. Just remember to make the constructor private
, so the user can't create multiple copies.
Upvotes: 1