Anon
Anon

Reputation: 2666

Difference between Singleton implemention using pointer and using static object

EDIT: Sorry my question was not clear, why do books/articles prefer implementation#1 over implementation#2?

What is the actual advantage of using pointer in implementation of Singleton class vs using a static object? Why do most books prefer this

class Singleton
{
  private:

    static Singleton *p_inst;
    Singleton();

  public:

    static Singleton * instance()
    {
      if (!p_inst)
      {
        p_inst = new Singleton();
      }

      return p_inst;
    }
};

over this

class Singleton
{
  public:
    static Singleton& Instance()
    {
        static Singleton inst;
        return inst;
    }

  protected:
    Singleton(); // Prevent construction
    Singleton(const Singleton&); // Prevent construction by copying
    Singleton& operator=(const Singleton&); // Prevent assignment
    ~Singleton(); // Prevent unwanted destruction
};

Upvotes: 30

Views: 26901

Answers (7)

Kalf
Kalf

Reputation: 1

How about a non-local static? Anyone see a problem with this?

class Singleton
{
    static Singleton singleton;
    Singleton();
    // etc

public:
    static Singleton &Instance() { return singleton; }
};

Singleton Singleton::singleton;

// etc

Upvotes: -3

Mike Seymour
Mike Seymour

Reputation: 254691

why do books/articles prefer implementation#1 over implementation#2?

Because most articles describing the Singleton anti-pattern don't fully understand all the hidden dangers when trying to implement it safely in C++. It's surprisingly difficult to get it right.

What is the actual advantage of using pointer in implementation of Singleton class vs using a static object?

Using a pointer, with new but no delete, ensures that the object will never be destroyed, so there is no danger of accessing it after its lifetime has ended. Combined with the "lazy" creation, the first time that it's accessed, this guarantees that all accesses are to a valid object. The disadvantages are that creation is not thread-safe, and that the object and any resources it acquires are not released at the end of the program.

Using a local static object, creation is thread-safe on any compiler that supports the C++11 threading model; also, the object will be destroyed at the end of the program. However, it is possible to access the object after its destruction (e.g. from the destructor of another static object), which could lead to nasty bugs.

The best option is to avoid static data, and globally-accessible data, as much as possible. In particular, never use the Singleton anti-pattern; it combines global, static data with weird instantiation restrictions that make testing unnecessarily difficult.

Upvotes: 23

Ivan Vergiliev
Ivan Vergiliev

Reputation: 3841

The second example is known by the name "Meyers' Singleton", because it was published first in either "Effective C++", or "More Effective C++". I'm not sure which one, but both were published after "Design Patterns" - so the Gang of Four might just as well have been unaware of the second pattern when their book was written.

Also, the first approach is much more standard for other languages - you can do the first one in Java or C#, but not the second, so people coming from different backgrounds could be another reason for the first one to be more famous.

On the technical side, with the first approach you can control when the singleton is destroyed, but this could also bring you a lot of headaches.

Upvotes: 5

Mankarse
Mankarse

Reputation: 40633

The second version (using a local static variable) has significant advantages.

It does not require use of the free-store, and so will not be detected as a memory leak. It is thread-safe (in C++11). It is shorter and simpler.

The only downsides are that it is impossible to make it portably threadsafe (for pre-C++11 compilers), and that it does not give you the option of explicitly destroying the singleton instance.

Upvotes: 11

Roddy
Roddy

Reputation: 68064

I'd always prefer the second, but the first does have a couple of potentially interesting advantages:-

  • Clarity - the checking of the pointer being null is effectively what the compiler does under the hood when constructing static objects. From a 'learning' perspective, it's instructive to understand what's happening when you use static objects in method scope.

  • Lazy Allocation - in the first case, the Singleton object is heap-allocated. If your function never runs, the object is never constructed and never consumes memory. But, in the second case, memory is assigned by the linker to hold the object before the program starts, even though 'construction' is lazy.

Upvotes: 4

CashCow
CashCow

Reputation: 31445

The second one has non-deterministic destruction. The first one, you are in control as to when you delete the pointer, if at all.

The first construct is not thread-safe, of course, but can be made so with boost::call_once (or std::call_once if available)

The second construct was common enough that many compilers made it thread-safe even if technically by the standard it isn't (although by the standard the object should only be created once, I'm not sure about the standard's view on completion of the construction before another thread uses it).

If there is no issue with the order of destruction then you can go ahead and use the static version, as long as your compiler guarantees it as thread-safe.

Upvotes: 3

juanchopanza
juanchopanza

Reputation: 227518

One advantage is that you do not have to check whether the singleton has already been instantiated.

Another is that you do not have to worry about de-allocating any memory.

Upvotes: 1

Related Questions