-1

I understand what a singleton does any why you would use one. I don't however understand how they work. If the singleton has been created once before and the "get instance" method has been called somewhere else how does it know where in memory the original instance of the singleton is? From reading the code I can't understand where it is coming from. Below is the simple example from the Microsoft MSDN website.

class Singleton {
public: 
    static Singleton* Instance();
protected: 
    Singleton();
private:
    static Singleton* _instance;
}

// Implementation 
Singleton* Singleton::_instance = 0;

Singleton* Singleton::Instance() {
    if (_instance == 0) {
        _instance = new Singleton;
    }
    return _instance;
}

I'm pretty sure it comes from this line here

Singleton* Singleton::_instance = 0;

But I have no idea what that line actually does or how it works.

Thanks in advance

Community
  • 1
  • 1
0C3D
  • 348
  • 3
  • 11
  • 5
    Singletons don't work. It is an anti-pattern. Don't use it. – Dietmar Kühl Sep 20 '15 at 12:59
  • 5
    You should look into what a `static` data member is. – juanchopanza Sep 20 '15 at 13:01
  • Your example isn't thread safe I believe. 2 threads can enter into `if (_instance == 0)` block at the same time, then you will get a memory leak, and each thread using a different instance. Also, avoid singletons if you can, they are almost always abused. – Preet Kukreti Sep 20 '15 at 13:02
  • 1
    It's a very bad example. If you are really in need of a Singleton use the design given in [this answer](http://stackoverflow.com/a/1008289/1413395). – πάντα ῥεῖ Sep 20 '15 at 13:03

4 Answers4

4

Quite a horrible example. Let's have a look at the details:

    static Singleton* Instance();

The function should return Singleton&, not Singleton*.

protected: 
    Singleton();

protected only makes sense for classes designed to be derived from. It does not make a lot of sense to derive from a Singleton. At best, it's an exotic special case. A Singleton constructor is typically private.

Singleton* Singleton::_instance = 0;

Since C++11, nullptr should be used for null pointers.

Singleton* Singleton::Instance() {
    if (_instance == 0) {
        _instance = new Singleton;
    }
    return _instance;
}

Not thread-safe. Let's say 3 threads (A, B and C) call Instance() at the same time. All three of them concurrently reach if (_instance == 0) for the first time. The condition is thus true for all of them, so all of them enter into the if block - resulting in three instances being created!

I'm pretty sure it comes from this line here

Singleton* Singleton::_instance = 0;

But I have no idea what that line actually does or how it works.

It initialises the static _instance member variable of the Singleton class. static in this context means that the variable exists independently of any Singleton instances, so you can access it in a static member function like Instance().


Since C++11, a thread-safe way to implement Singletons is to instead use a static local variable:

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

The technique has existed for a long time, but it's thread-safe only since C++11 because only the C++11 standard officially acknowledged the existence of multi-threading, including certain guarantees for local static variables.

The drawback of this technique is that you can run into order-of-destruction issues if you have multiple Singleton classes and the destructor of one accesses another Singleton.

There are ways around this issue, but I will not go into further detail here, because now that you have learnt a few things about Singleton - Do not use the pattern.

Most programmers these days have learnt the hard way that Singletons are just global variables in disguise and should be used almost as rarely. They create global dependencies all over your code, making testing and modularisation harder or impossible, and are hard to implement correctly and safely. Singleton is the number one black sheep in the Gang of Four book.


By the way, look what Microsoft themselves are saying at the top of the page you refer to:

This content is outdated and is no longer being maintained. It is provided as a courtesy for individuals who are still using these technologies.

Christian Hackl
  • 27,051
  • 3
  • 32
  • 62
  • Excellent answer. OP: follow this advice and don't use singletons. – elixenide Sep 20 '15 at 13:56
  • This is a really good answer and it was difficult to choose which was more helpful to me. I chose the other as I was interested in exactly how it worked under the hood. You say do not use this pattern but do you agree that there is a time and place? I am developing a program which will need to store non static information in ram that will be needed over and over again. This information will need to be accessed by more than one object and there may not always be an object pointing to this information. Is it okay to use a singleton in this case? Is there a better alternative? – 0C3D Sep 20 '15 at 23:03
  • After doing some more research on static variables I am beginning to understand everything a little more. I see now that for what I want to do a singleton isn't required I can just use a static variable. When is a singleton a good idea? If ever? – 0C3D Sep 21 '15 at 10:42
2

If the singleton has been created once before and the "get instance" method has been called somewhere else how does it know where in memory the original instance of the singleton is?

Static data are typically stored in .data section of your executable.

When your code uses static data it will be translated to assembly instruction that references some absolute address from data section, e.g.

A1 00 F0 22 01       mov         eax,dword ptr ds:[0122F000h]

Your code is compiled and linked under assumption that your program will be loaded into some expected base address.This is not always the case, therefore your executable also contains relocation section, which contains offset information about where in your file are those absolute addresses.

When your program is loaded into memory, OS will take care that those absolute addresses are replaced with the real ones.

Karlis Olte
  • 353
  • 1
  • 3
  • 10
  • 1
    A very implementation-centric answer. It's not wrong as far as I can see, but the OP doesn't even know what `static` means, so I wonder if this is actually helpful for him or her. And of course, the C++ standard does not mandate how static data is stored. Perhaps you should expand the "typically" in your answer along the lines of *"although the standard doesn't say so, implementations typically implement `static` variables by [...]".* – Christian Hackl Sep 20 '15 at 13:32
-2

Here is a less confusing example. Let's just keep Singleton as a design pattern name and not use it as the Class name.

Logger* Logger::m_pInstance = NULL; 

/* Use this to get the instance of Logger instead of "new" */
Logger* Logger::Instance()
{

     if (!m_pInstance) {  // Only allow one instance of class to be generated.
         m_pInstance = new Logger;
     }

     return m_pInstance;
}


/* some other method in the logger class */
bool Logger::openLogFile(std::string _logFile)
{

   ...
   ...
   ...

}

So basically, if you want an instance of this class, you call the instance() method. It will always return the EXACT SAME object to you.

Yes some people don't like Singleton for some reason or another... No idea why. All patterns have their place and use.

Better to learn as many design patterns and when to use them, than not know them.

https://en.wikipedia.org/wiki/Software_design_pattern

  • This implementation is badly flawed. You can't use `Logger` from separate threads. – πάντα ῥεῖ Sep 20 '15 at 13:24
  • 2
    *"No idea why."* - For the same reasons that global variables are disliked. – Christian Hackl Sep 20 '15 at 13:27
  • But it is nice to know that Globals exists. The problem is abuse of globals or Singletons. Understanding what they are and what they do is a positive thing. The poster was asking what it was, not WHEN to use it. – Michael Pawlowsky Sep 20 '15 at 14:00
  • 1
    The problem with Singletons is that it's a "design pattern". The word "design pattern" has a positive sound to it, whereas "global variable" reeks of "evil" and "don't use". People use Singletons and think they have created a "clean design", while a global variable would tell them that more rethinking and refactoring is necessary. It's a psychology issue. – Christian Hackl Sep 20 '15 at 14:06
  • As for thread safe... you just need to realize that it will be a different instance in every thread you call it. So Unsafe is not exactly correct. It is safe as long as you understand what it is doing. – Michael Pawlowsky Sep 20 '15 at 14:13
  • @MichaelPawlowsky: The best definition of "thread-safe" I know is "documentation exists that tells you about guaranteed behaviour in the presence of multiple threads or lack thereof". – Christian Hackl Sep 20 '15 at 17:43
-3

Singletons can be extremely useful at times.

All this is saying is:

Singleton* Singleton::Instance() {
    if (_instance == 0) {
        _instance = new Singleton;
    }
    return _instance;
}

has this Object (of Type Singleton in this case) already been created, if so, return it. If not create the new "Singleton" object and return it.

In other words no matter how many times you call the Instance() method, it will always return the same object to you.