I usually implement the singleton pattern this way :
class Singleton
{
public:
virtual ~Singleton() {}
static Singleton& GetInstance()
{
static Singleton instance;
return instance;
}
private:
Singleton();
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
}
Recently, I ran into this implementation, which is slightly different :
class Singleton
{
public:
Singleton();
virtual ~Singleton() {}
static Singleton& GetInstance()
{
return instance;
}
private:
Singleton(const Singleton&);
Singleton& operator=(const Singleton&);
static Singleton instance;
}
Singleton Singleton::instance;
Which implementation is better ?
Isn't it dangerous not to make the constructor private (2nd implementation) ?
Thanks.
There is a difference. In first case instance is initialized on first call of the function. In second case it is initialized when program starts.
If you make a public constructor - It's not a singleton, since it's can be created by anyone
I need not repeat the good point about lazy construction of the singleton made in other answers.
Let me add this:
public:
Singleton();
virtual ~Singleton() {}
The designer of this particular class felt a need to allow:
derivation from this Singleton class, say the derived class is called DerSingleton
DerSingleton can have instances which can be deleted with a pointer to Singleton (so DerSingleton is not a singleton)
Any instance of DerSingleton is also a Singleton instance by definition, so it follows that if DerSingleton is instanciated, Singleton is not a singleton.
So this design asserts two things:
this class is a singleton
this class is not a singleton
The main difference in behavior will come if you try to use the singleton during initialization of another namespace level variable or class static member. In the first case, because the actual object is created on demand during the first function call, the behavior during contruction will be well defined. In the second case, all bets are off, since the relative order of initialization of static objects from different translation units is undefined.
Also note that while the first one is safe during construction, it might not be during destruction. That is, if an object with static storage duration does not use the singleton during construction, it could be initialized before the singleton instance. The order of destruction is reversed from the order of construction, and in this particular case the singleton would be destroyed before the other object. If that object uses the singleton in its destructor, it will cause undefined behavior.
The second implementation is wrong. The default constructor should be private. As it is, it is not a singleton per se. Besides that, the differences between the implementations are mentioned in #Andrew and #Brady answers.
One important difference between the two is that the creation of the instance in the second example is thread-safe.
You're absolutely right though, the constructor should be private.
Here's a related question: https://stackoverflow.com/a/10479084/1158895
Related
I am trying to implement a singleton class that has to be used in two different threads, one sets up its member variables and the other one uses them, but the constructor is being called twice so I cannot use the members set in the first thread because they have their default value.
The implementation is quite standard, a static function that returns a reference to a static member in that function, I have tried to return a pointer, create a raw pointer and return it and the constructor always is called twice.
class Singleton
{
public:
static Singleton &getInstance()
{
static Singleton instance;
return instance;
}
// public methods
private:
Singleton();
Singleton(const Singleton &) = delete;
Singleton(Singleton &&) = delete;
Singleton &operator=(const Singleton &) = delete;
Singleton &operator=(Singleton &&) = delete;
// member variables
};
The thread trying to access to the singleton has been created using std::async(std::launch::async, lambda)
I expected that instance's constructor is called just the first time I call this function, but the second time instance has a different memory direction.
The C++11 standard guarantees that static local variables are only created once.
This leaves us with the following options:
Your compiler isn't C++11-compliant. Could be because it's old or
you're using the wrong options.
Your Singleton throws an (uncaught) exception, and the
initialization is attempted again.
Your constructor calls getInstance(), which results in undefined
behavior.
The above assumes you've implemented the Singleton pattern correctly. You could've also just messed up in some way, but I can't tell because you haven't provided the full code.
All the info taken from cppreference on static local variables.
If I return a reference to my instance of MySingleton from GetInstance() instead of the pointer in my code below, it will be valid, but is using the pointer in this way also valid?
I assume my pointer will only get initialized once because it is static, but not not sure.
I know the correct way by using raw pointers within a singleton is to check if the pointer is first null before assigning it, but wondering if the below code is also valid. Thanks
class MySingleton
{
public:
static MySingleton* GetInstance()
{
static MySingleton* inst = new MySingleton();
return inst;
}
private:
MySingleton(){};
};
EDIT: I haven't seen this exact implementation for a Singleton implemented in the reported duplicate question
Your implementation is acceptable (as is any other) as long as any one of the following holds:
Your singleton does not acquire any external resources (anything: file handles, network connections, shared memory) for longer than a single exception-safe method invocation.
The last user of your singleton deletes the instance manually.
Otherwise something serious can leak.
You can wrap the instance in something automatic, like std::unique_ptr, but this immediately casts usual singleton lifetime issues.
See std::call_once and std::once_flag for implementing singleton pattern. Your implementation will lead to troubles in a multithreaded environment.
Most of is seem to have missed the simplest possible form of C++ singleton AKA Scott Meyer's Singleton. Ever since C++11 it has become as easy as a pie:
class singleton{
singleton();
singleton(singleton&&)=delete;
singleton(singleton const&)=delete;
void operator(singleton&&)=delete;
void operator(singleton const&)=delete;
//...
public:
static auto& singleton::instance(){
static singleton val{};
return val;
}
};
No need for complex code.
I will demonstrate my question using a Singleton pattern but it is a broader question. Please spare me the "Singletons are evil" lectures.
Version 1 of Singleton
class Singleton
{
public:
static Singleton& getInstance()
{
static Singleton instance; // This becomes a class member in Ver.2
return instance;
}
private:
// Constructor, forbid copy and assign operations etc...
}
Version 2 of Singleton
class Singleton
{
public:
static Singleton& getInstance()
{
return instance;
}
private:
static Singleton instance; // I'm here now!
// Constructor, forbid copy and assign operations etc...
}
I will now explain what I think will be the difference is between the two:
Version 1 instance will only be initialized once the flow of the program reaches the actual definition of instance (i.e some part of the program requests an instance using Singleton::getInstace()). Lazy instantiated in other words.
It will only be destroyed when the program terminates.
Version 2 instance will be initialized at the start of the program, before main() is called. Will also be destroyed only when the program terminates.
First of all, am I correct in the above assumptions?
Second, Is this behavior of initialization universal (say for global variables and functions)?
Last, Are there any other nuances I should be alerted about concerning this?
Thanks!
You are correct.
You should also notice that the 2nd version does not guarantee when will the object be created, only that it will be before the main function is called.
This will cause problems if that singleton depends on other singletons and etc
That is, the first version will give you greater control over your code, initialization order and of course - less bugs :)
someone told me just to write singleton as a local class, is that true?
I am wondering why using the local class can ensure thread safety.
#include <boost/utility.hpp>
class singleton : private boost::noncopyable {
public:
static singleton& instance() {
static singleton inst;
return inst;
}
private:
singleton() = default;
~singleton() = default;
};
The construction of local static variables is guaranteed to be thread-safe.
Also, avoid singletons at all cost. They are just as terrible as globals are.
Take a look at this post: what is correspoding feature for synchronized in java?feature-for-synchronized-in-java
Basically it states that C++ doesn't has a language level feature for locking mechanisms, wich you need to make your singelton class threadsafe, though this articel http://en.wikipedia.org/wiki/Double-checked_locking about the Double Checked Locking Pattern states, that no locking is needed for singletons (an example is included for c).
Is it possible to create a class which could be constructed just one time? If you would try to create an other instance of it, a compile-time error should occure.
Instantiation is dynamic, at run time. Compilation errors are at compile time. So the answer is no, it's not possible to get a compilation error on any second instantiation.
You can however use a singleton, but do consider very carefully whether it's really needed.
The classes with only one instances are called singleton classess,
There are many ways to perform that. The simplest is shown below
class MySingleton
{
public:
static MySingleton& Instance()
{
static MySingleton singleton;
return singleton;
}
// Other non-static member functions
private:
MySingleton() {}; // Private constructor
MySingleton(const MySingleton&); // Prevent copy-construction
MySingleton& operator=(const MySingleton&); // Prevent assignment
};
Why compile error? You just need to implement Singleton design pattern, I think.
Look here