0

I would like to discuss the nuances of implementation of well known Singleton design pattern. Here there are two implementations in C++:

http://www.codeproject.com/Articles/1921/Singleton-Pattern-its-implementation-with-C

and another one is this:

#ifndef __SINGLETON_HPP_
#define __SINGLETON_HPP_

template <class T>
class Singleton
{
public:
  static T* Instance() {
      if(!m_pInstance) m_pInstance = new T;
      assert(m_pInstance !=NULL);
      return m_pInstance;
  }
protected:
  Singleton();
  ~Singleton();
private:
  Singleton(Singleton const&);
  Singleton& operator=(Singleton const&);
  static T* m_pInstance;
};

template <class T> T* Singleton<T>::m_pInstance=NULL;

#endif

If we compare this versions what advantages and disadvantages does they have and eventually, which version is preferred?

Narek
  • 38,779
  • 79
  • 233
  • 389
  • Yes it's a pattern, but it doesn't mean you should use it. You'll be choosing the lesser of two evils. I don't imagine you really need it. – Peter Wood Jan 23 '12 at 07:48
  • 1
    @PeterWood It's not a pattern - it's an anti-pattern – BЈовић Jan 23 '12 at 07:52
  • 2
    Do you know that using include guards named like `__SINGLETON_HPP_` is actually wrong in addition to being ugly? – 6502 Jan 23 '12 at 07:55
  • @VJovic:Why is sigleton an antipattern? – Cratylus Jan 23 '12 at 07:58
  • @VJovic Anti-patterns are patterns, too. – Peter Wood Jan 23 '12 at 08:59
  • @user384706 Everything that uses a singleton object is being told the implementation details. Most parts of a system won't really be bothered that only instance of the object should exist, or that there should be a global point of access to it. They just need an object to fulfil a collaboration. My advice is just make one, and pass it to objects that need it. Define an interface and it will make your testing easier too. – Peter Wood Jan 23 '12 at 09:06
  • @user384706 One of the biggest reason is that it makes unit testing very difficult. – BЈовић Jan 23 '12 at 09:20
  • @PeterWood:I don't follow:how does the singleton tell the implementation details? – Cratylus Jan 23 '12 at 09:38
  • @user384706 It's telling you it's a singleton, even if you don't care. 'I don't care', says my code, 'I just want an object I can use'. – Peter Wood Jan 23 '12 at 12:48

2 Answers2

1

The main differences between these two implementations are:

  • the first adds a redundant flag to tell you whether or not a pointer is null, and so takes up slightly more memory than it needs to;
  • the second is not a singleton at all: there is nothing to stop T from having a public constructor, thereby breaking the singleton restriction.

The main problems with both of them (beyond the fact that a singleton is never a good idea in the first place) are:

  • construction is not thread-safe; calling Instance() from two threads could cause two objects to be created;
  • both leak memory; they dynamically create the object with new, but never call delete.

In C++, it is very difficult to manage the lifetime of a globally-accessible object safely; for that reason (and many others), I would recommend avoiding the Singleton anti-pattern altogether. Create objects in well-managed scopes, and pass references where needed.

If you really want a globally-accessible instance, then in most cases the simplest and safest option is:

static Singleton & Instance() {
    static Singleton instance;
    return instance;
}

This will be created the first time the function is called, and a C++11 compiler must ensure that this is thread-safe. The remaining problem is that the instance might be destroyed before other static objects, causing a disaster if their destructors try to access it.

Community
  • 1
  • 1
Mike Seymour
  • 249,747
  • 28
  • 448
  • 644
0

Basically, both implementations are the same. Implementation on CodeProject provides 2 things:

  • singleton status flag, which allows you to mark singleton as "old" from outside (and then properly reinstantiate it from inside)
  • getInstance method, which is nothing special from singleton's perspective. However this makes the code way more readable for other persons AND yourself after some time.

Just the difference between
Cat::meow(); and
Cat::getInstance()->meow()

friendzis
  • 799
  • 6
  • 17