After working with C++ for a while, we all come across situations where we need to create one and only one instance of a given object type. However, depending on your needs, there's more than one way to go about implementing a singleton. All of the implementations will have certain characteristics in common. For instance, the class constructor will be private to prevent anyone from creating an instance of the class directly. (The destructor may need to be private as well, but we'll discuss that below.) Instead, a static getInstance() method will provide access to the one and only class instance:

class MyObject
{
private:
    MyObject();

public:
    // We'll see below that the type returned by this method
    // may vary depending on how you implement the singleton.
    static MyObject& getInstance();
};

We'll take a look at the "permanent" singleton, the "lazy" singleton, and the "disappearing" singleton. Though these descriptions aren't official or even commonly adopted, they accurately describe the behavior of the singleton object.

The Permanent Singleton

The "permanent" singleton is exactly what its name implies. It's created automatically when your application starts and it remains intact until your application terminates.

// Allocate the object on the heap and initialize it before
// the application begins execution.
static MyObject instance;
MyObject& MyObject::getInstance()
{
    return instance;
}

Creating a static instance of the class ensures the object is initialized and ready for use when the application starts. Because the object is instantiated before the application begins execution, this implementation is advantageous in multithreaded environments since there is no need to worry about thread contention trying to instantiate the object. However, we will need to ensure the object does not carry any initialization dependencies on other statically instantiated objects and that it can actually allocate any internal resources during its early initialization. (Read about Schwarz Counters for more information on handling initialization dependencies between static objects.)

Because the singleton is created when the application starts and can never be destroyed, it's internal state is maintained throughout the lifetime of the application.

Most likely, we will want to make the class destructor private to prevent anyone from doing something like this:

MyObject& niceObject = MyObject::getInstance();
MyObject* evil_ptr = &niceObject;
delete evil_ptr;

Hopefully, no one would perform this exact series of steps, but if the object reference is ever converted to a pointer, it becomes possible to delete the object and future calls to getInstance() will return a bad pointer.

Advantages:

  • Avoid threading problems associated with instantiation.
  • Maintains object state throughout the lifetime of the application.

Disadvantages:

  • Resources are allocated permanently.

The Lazy Singleton

If your singleton object consumes significant resources or it may not be needed within every instance of your application, you may prefer to use the "lazy" singleton. We can avoid creating an instance of the class until it's needed by the application.

MyObject& MyObject::getInstance()
{
    // Allocate space on the heap for the object instance. It will
    // be initialized the first time this method is called.
    static MyObject instance;
    return instance;
}

Or we might prefer to allocate memory for the object when it's first needed:

MyObject* MyObject::getInstance()
{
    // Only allocate space on the heap for an instance pointer.
    static MyObject* instance = NULL;
    if (instance == NULL)
    {
        instance = new MyObject();
    }
    return instance;
}

However, waiting to either allocate or initialize the singleton instance means we also need to exercise some caution if the object is used in a multithreaded environment. The second implementation carries the risk of allocating multiple instances of the class. While the first implementation cannot allocate multiple instances, it can result in multiple calls to the class constructor. A locking mechanism will need to be placed around the declaration of the singleton object in the first instance and around the if block in the second.

Thinking about the class destructor, we still don't want to make it public. We might think we could use the destructor to reset the instance pointer, allowing us to only consume any class resources when we needed the object and free them by destroying the object when we were done with it. However, there's no way to guarantee we wouldn't be deleting a pointer that was still being reference elsewhere in the application. To do that we would need some sort of reference counting on the object, which leads us to the next singleton implementation.

Advantages:

  • Avoids resource allocation until the object is needed.
  • Maintains object state throughout the lifetime of the application.

Disadvantages:

  • Once resources are allocated, they're allocated permanently.
  • Not thread-safe without additional safeguards.

The Disappearing Singleton

Is there a way we can implement a singleton that's guaranteed to only be around when we need it - a singleton that "disappears" when we don't want it anymore? While standard C++ doesn't provide us with a way to do this, we can use the popular Boost libraries to help us out.

shared_ptr<MyObject> MyObject::getInstance()
{
    static weak_ptr<MyObject> instance;

    shared_ptr<MyObject> ptr = instance.lock();
    if (!ptr)
    {
        ptr.reset(new MyObject());
        instance = weak_ptr<MyObject>(ptr);
    }
    return ptr;
}

The boost::weak_ptr<> and boost::shared_ptr<> templates allow us to maintain a reference count on our singleton object. When a shared_ptr is allocated, it increments the reference count on an object. When it goes out of scope, it decrements the reference count. When the reference count hits zero, the object is deleted. If we couple the shared_ptr with the weak_ptr, we have a way to track usage of our singleton object and free it when it's no longer needed. A shared_ptr is created for our class instance when it's first needed and the weak_ptr "follows" it around until it's deleted. Trying to lock() the weak_ptr will return the singleton instance of our class, or it will return an empty shared_ptr, indicating we need to create a new singleton instance.

The destructor for our class can be public so it can be accessed by the Boost templates, but a better approach would be to keep it private and add the weak_ptr and shared_ptr classes as friends of our class. This will prevent anyone from doing something like this:

shared_ptr<MyObject> nice_ptr = MyObject::getInstance();
MyObject* evil_ptr = nice_ptr.get();
delete evil_ptr;

One caveat with the disappearing singleton is that it may not maintain state across calls to getInstance(). Our first two implementations maintained object state for everyone calling getInstance() because we never destroyed the singleton object. If the singleton needs to maintain any state information across the lifetime of the application, it will need some additional help.

Advantages:

  • Avoids resource allocation until the object is needed.
  • Frees resources when they are no longer needed.

Disadvantages:

  • Not thread-safe without additional safeguards.
  • Does not maintain object state.

Before jumping on any particular singleton implementation, it's a good idea to consider how the singleton object will be used within your application. Is threading performance an issue? Is resource usage an issue? Is consistent internal state an issue? Any approach will have it's own set of advantages and disadvantages that should be considered, and it is probably wise to document the reasoning for selecting a particular approach within the object's getInstance() implementation.