C++ Singleton Implementation

Singleton is the simplest and probably the most widely used of all design patterns. It’s so popular that some IDEs (like SlickEdit) have templates for its generation. The purpose of this design pattern is to ensure that only one instance of a class is created.
So, why discuss Singleton?

The implementation suggested in the GoF book always bothered me:

class CGoFSingleton {
public:
	// Returns the single instance of the object
	static CGoFSingleton* getInstance()
	{
		// Check if the instance has been created already
		if (0 == _instance) {
			// if not, then create it
			_instance = new CGoFSingleton;
		}
		// return the single instance
		return _instance;
	}
	virtual ~CGoFSingleton();
protected:
	// Constructor - protected so users cannot call it
	CGoFSingleton();
private: 
	// Pointer to the single instance of the object
	static CGoFSingleton* _instance;

	// Copy constructor - declared but not defined
	CGoFSingleton(const CGoFSingleton& src);

	// Assignment operator - declared but not defined
	CGoFSingleton& operator=(const CGoFSingleton& src);
};

What I don’t like about it is that:

  • the destructor will not be invoked;
  • it leaves a memory leak.

The memory leak of course is not an issue – the OS will reclaim the memory after the program is terminated. It will obfuscate the results from a memory leak detection application, but that’s not an issue as well.
But what if you want to free some resources other than memory in the destructor?

The GoF Singleton doesn’t clean up after itself. There is another implementation – Meyers Singleton, that prevents memory leaks:

class CMeyersSingleton {
public:
	// Returns the single instance of the object
	static CMeyersSingleton& getInstance()
	{
		static CMeyersSingleton theInstance;
		return theInstance;
	}
	virtual ~CMeyersSingleton();
protected:
	// Constructor - protected so users cannot call it
	CMeyersSingleton();
private: 
	// Copy constructor - declared but not defined
	CMeyersSingleton(const CMeyersSingleton& src);

	// Assignment operator - declared but not defined
	CMeyersSingleton& operator=(const CMeyersSingleton& src);
};

The Meyers Singleton introduces another problem – static initialization order fiasco, so be careful if you need to invoke some methods of another static object in your constructor.
The Meyers Singleton is what I use in my code.

You can leave a response, or trackback from your own site.

Leave a Reply