C++ singleton vs. global static object

C++StaticSingletonGlobal Variables

C++ Problem Overview


A friend of mine today asked me why should he prefer use of singleton over global static object? The way I started it to explain was that the singleton can have state vs. static global object won't...but then I wasn't sure..because this in C++.. (I was coming from C#)

What are the advantages one over the other? (in C++)

C++ Solutions


Solution 1 - C++

Actually, in C++ preferred way is local static object.

Printer & thePrinter() {
    static Printer printer;
    return printer;
}

This is technically a singleton though, this function can even be a static method of a class. So it guaranties to be constructed before used unlike with global static objects, that can be created in any order, making it possible to fail unconsistently when one global object uses another, quite a common scenario.

What makes it better than common way of doing singletons with creating new instance by calling new is that object destructor will be called at the end of a program. It won't happen with dynamically allocated singleton.

Another positive side is there's no way to access singleton before it gets created, even from other static methods or from subclasses. Saves you some debugging time.

Solution 2 - C++

In C++, the order of instantiation of static objects in different compilation units is undefined. Thus it's possible for one global to reference another which is not constructed, blowing up your program. The singleton pattern removes this problem by tying construction to a static member function or free function.

There's a decent summary here.

Solution 3 - C++

> A friend of mine today asked me why should he prefer use of singleton over global static object? The way I started it to explain was that the singleton can have state vs. static global object won't...but then I wasn't sure..because this in C++.. (I was coming from C#)

A static global object can have state in C# as well:

class myclass {
 // can have state
 // ...
 public static myclass m = new myclass(); // globally accessible static instance, which can have state
}

> What are the advantages one over the other? (in C++)

A singleton cripples your code, a global static instance does not. There are countless questions on SO about the problems with singletons already. Here's one, and another, or another.

In short, a singleton gives you two things:

  • a globally accessible object, and
  • a guarantee that only one instance can be created.

If we want just the first point, we should create a globally accessible object. And why would we ever want the second? We don't know in advance how our code may be used in the future, so why nail it down and remove what may be useful functionality? We're usually wrong when we predict that "I'll only need one instance". And there's a big difference between "I'll only need one instance" (correct answer is then to create one instance), and "the application can't under any circumstances run correctly if more than one instance is created. It will crash, format the user's harddrive and publish sensitive data on the internet" (the answer here is then: Most likely your app is broken, but if it isn't, then yes, a singleton is what you need)

Solution 4 - C++

Reason 1:
Singletons are easy to make so they are lazy build.
While you can do this with globals it take extra work by the developer. So by default globals are always initialized (apart from some special rules with namespaces).

So if your object is large and/or expensive to build you may not want to build it unless you really have to use it.

Reason 2:
Order of initialization (and destruction) problem.

GlobalRes& getGlobalRes()
{
    static GlobalRes instance;  // Lazily initialized.
    return instance;
}


GlobalResTwo& getGlobalResTwo()
{
    static GlobalResTwo instance;  // Lazy again.
    return instance;
}


// Order of destruction problem.
// The destructor of this object uses another global object so
// the order of destruction is important.
class GlobalResTwo
{
    public:
        GlobalResTwo()
        {
            getGlobalRes();
            // At this point globalRes is fully initialized.
            // Because it is fully initialized before this object it will be destroyed
            // after this object is destroyed (Guaranteed)
        }
        ~GlobalResTwo()
        {
            // It is safe to use globalRes because we know it will not be destroyed
            // before this object.
            getGlobalRes().doStuff();
        }
};

Solution 5 - C++

Another benefit of the Singleton over the global static object is that because the constructor is private, there is a very clear, compiler enforced directive saying "There can only be one".

In comparison, with the global static object, there will be nothing stopping a developer writing code that creates an additional instance of this object.

The benefit of the extra constraint is that you have a guarantee as to how the object will be used.

Solution 6 - C++

Using Singleton("construct on first use") idiom, you can avoid static initialization order fiasco

Solution 7 - C++

In C++, there's not a huge amount of difference between the two in terms of actual usefulness. A global object can of course maintain its own state (possibly with other global variables, though I don't recommend it). If you're going to use a global or a singleton (and there are many reasons not to), the biggest reason to use a singleton over a global object is that with a singleton, you can have dynamic polymorphism by having several classes inheriting from a singleton base class.

Solution 8 - C++

OK, there are two reasons to go with a singleton really. One is the static order thing everyone's talking about.

The other is to prevent someone from doing something like this when using your code:

CoolThing blah;
gs_coolGlobalStaticThing = blah;

or, even worse:

gs_coolGlobalStaticThing = {};

The encapsulation aspect will protect your instance from idiots and malicious jerks.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionTomView Question on Stackoverflow
Solution 1 - C++vavaView Answer on Stackoverflow
Solution 2 - C++rlbondView Answer on Stackoverflow
Solution 3 - C++jalfView Answer on Stackoverflow
Solution 4 - C++Martin YorkView Answer on Stackoverflow
Solution 5 - C++Andrew ShepherdView Answer on Stackoverflow
Solution 6 - C++aJ.View Answer on Stackoverflow
Solution 7 - C++copproView Answer on Stackoverflow
Solution 8 - C++SeanView Answer on Stackoverflow