C++ different singleton implementations
Asked Answered
F

5

2

I usually implement the singleton pattern this way :

class Singleton
{
    public:
        virtual ~Singleton() {}

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

    private:
        Singleton();
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);
}

Recently, I ran into this implementation, which is slightly different :

class Singleton
{
    public:
        Singleton();
        virtual ~Singleton() {}

        static Singleton& GetInstance()
        {
            return instance;
        }

    private:
        Singleton(const Singleton&);
        Singleton& operator=(const Singleton&);

        static Singleton instance;
}

Singleton Singleton::instance;

Which implementation is better ?

Isn't it dangerous not to make the constructor private (2nd implementation) ?

Thanks.

Fontes answered 20/7, 2012 at 13:34 Comment(0)
D
4

There is a difference. In first case instance is initialized on first call of the function. In second case it is initialized when program starts.

If you make a public constructor - It's not a singleton, since it's can be created by anyone

Dorsman answered 20/7, 2012 at 13:36 Comment(0)
R
4

I need not repeat the good point about lazy construction of the singleton made in other answers.

Let me add this:

public:
    Singleton();
    virtual ~Singleton() {}

The designer of this particular class felt a need to allow:

  • derivation from this Singleton class, say the derived class is called DerSingleton
  • DerSingleton can have instances which can be deleted with a pointer to Singleton (so DerSingleton is not a singleton)

Any instance of DerSingleton is also a Singleton instance by definition, so it follows that if DerSingleton is instanciated, Singleton is not a singleton.

So this design asserts two things:

  • this class is a singleton
  • this class is not a singleton
Rea answered 20/7, 2012 at 14:13 Comment(0)
I
3

The main difference in behavior will come if you try to use the singleton during initialization of another namespace level variable or class static member. In the first case, because the actual object is created on demand during the first function call, the behavior during contruction will be well defined. In the second case, all bets are off, since the relative order of initialization of static objects from different translation units is undefined.

Also note that while the first one is safe during construction, it might not be during destruction. That is, if an object with static storage duration does not use the singleton during construction, it could be initialized before the singleton instance. The order of destruction is reversed from the order of construction, and in this particular case the singleton would be destroyed before the other object. If that object uses the singleton in its destructor, it will cause undefined behavior.

Inkling answered 20/7, 2012 at 13:45 Comment(0)
A
1

The second implementation is wrong. The default constructor should be private. As it is, it is not a singleton per se. Besides that, the differences between the implementations are mentioned in @Andrew and @Brady answers.

Anetta answered 20/7, 2012 at 13:40 Comment(0)
W
0

One important difference between the two is that the creation of the instance in the second example is thread-safe.

You're absolutely right though, the constructor should be private.

Here's a related question: https://mcmap.net/q/998450/-singleton-pattern-does-early-binding-with-static-variables-involved-diminish-the-need-of-mutex-locks

Whereat answered 20/7, 2012 at 13:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.