Table of Contents
What is the Singleton Pattern?
The Singleton Pattern makes sure a class has only one instance and provides a way to access it globally. It’s typically preferred, within the development community, to find alternatives to using global access, if possible. What the Singleton Pattern does better than say, a global variable, is that it’s access is controlled within the class and can be protected if necessary (when lazy instantiation is used).
The class diagram for the Singleton Pattern is pretty simple. It has just one class (Singleton) that has a private static member instance of itself as well as a static GetInstance() method for clients to access the instance of the class. Note that the Singleton class constructor is private as well. Thus restricting the ability to create a Singleton object to only within the scope of the Singleton class.
Common Singleton implementation using C++
Singleton.h
Singleton.cpp
Above is the implementation of the Singletom Pattern in it’s simplest form. There is a flaw with this implementation, however. Let’s discuss in the next section.
Thread Safe Singleton Implementation using C++
Our common implementation of the Singleton currently does not protect the creation of the instance in multithreaded environments. Without some kind of synchronization, we could see the undesirable behavior of multiple instances of our Singleton object. The creation of the instance can easily be protected by using a mutex. See the updated implementation below.
Singleton.h (protected creation)
Singleton.cpp (protected creation)
There is another approach that doesn’t require a mutex but it will depend on whether or not we have all the info available to create our Singleton object. Rather than use a lazy instantiation, create our Singleton object during the initial assignment of our instance vs. in GetInstance().
Use Caution When Using Singleton
The Singleton pattern is considered the most misused pattern by developers. Many times, it’s used to just replace existing global variables. While it could be considered better than having a global variable, the access is still global, just better encapsulated and protected. Keep in mind that the point of the pattern is to make sure there is only one instance of the given class. Only consider applying the pattern when that is the case. Also, consider passing the Singleton around to the objects that use it versus using the static GetInstance() everywhere (tempting to do, I know). Doing so provides more flexibility to the design by reducing the global visibility of the Singleton object by the objects that use it.
Additionally, I would recommend avoiding the lazy instantiation approach with the Singleton pattern in a real-time environment that doesn’t have its own heap implementation. This is because the creation of the object is not real-time friendly and you could run into latencies if the Singleton’s first use (time of creations) is on a real-time critical path. You would want to make sure the object is created in a non-real-time sequence (at system initialization, for example).
Resources on Singleton Pattern
Here are some resources I recommend for more detail and point of views on the Singleton pattern.
Conclusion
As with any pattern, the Singleton pattern can be very useful when applied appropriately. If the pattern is new to you, experiment with it to better understand how it can be used. As always, feel free to share any feedback or questions you may have in the comments below.
Arne Mertz
Instead of making the instance variable a pointer you can more easily return a function local static:
class Singleton {
public:
static Singleton& GetInstance() {
static Singleton instance;
return instance;
}
private:
Singleton();
~Singleton();
};
This way, the Singleton is also destroyed at the end of the program which is not the case with your implementation (a unique_ptr would help).
The virtual destructor is not needed by the way, since you don’t derive from Singleton.
In addition, I’d always return a reference here, since there will always be an object, i.e. you won’t get a nullptr, so there is no point for a pointer at all.
Robert Larson
Hi Arne,
Thanks for reading my post! I appreciate the feedback. I do like your suggestion to remove the pointer and return a reference to a local static instance. Especially if the instantiation is on a realtime critical path as it was avoid a dynamic allocation on heap. I do think that is a better solution than using a pointer but in the case where one was used, I agree using unique_ptr would improve the solution when the program exits.
Not sure why I used a virtual destructor. It looks like my Eclipse configuration creates the class like that by default. Regardless, my mistake and thanks for pointing it out.
Much respect,
Bob