Singleton Pattern

3da8dff723c96426428d0fd0b9e8ec6c
0
Cybrid 101 Nov 05, 2005 at 13:08

Well, I’m totally new to this kind of class, so after searching a bit I found out this tuto about Singleton Pattern What I still don’t understand very well is that in this piece of code

class Singleton 
  {
  public:
      static Singleton* Instance();
  protected:
      Singleton();
      Singleton(const Singleton&);
      Singleton& operator= (const Singleton&);
  private:
      static Singleton* pinstance;
  };

How can be a method a pointer to an object?.
static Singleton* Instance();

Or maybe my question is wrong?. I still don’t have it very clear.

Thanks in advance :mellow:

18 Replies

Please log in or register to post a reply.

6aa952514ff4e5439df1e9e6d337b864
0
roel 101 Nov 05, 2005 at 13:28

Maybe I misunderstood your question, but

static Singleton* Instance();

means: we have a static function named Instance that returns a pointer to a Singleton object.

884f4b6b49f0f04a9cae99abcc8a1bf3
0
hauptman 101 Nov 05, 2005 at 14:30

That’s not a pointer to an object. It means that the function Instance will return a pointer to an object of the type Singleton.

3da8dff723c96426428d0fd0b9e8ec6c
0
Cybrid 101 Nov 05, 2005 at 15:24

OMG!!!, how can I be so blind!!! :surprise:

Thanks to you both :happy:

6f0a333c785da81d479a0f58c2ccb203
0
monjardin 102 Nov 06, 2005 at 14:27

I usually do the following so that you don’t have to worry about doing a new/delete on your instance:

class Singleton 
  {
  public:
      static inline Singleton& Instance() {
            static Singleton instance;
            return instance;
      }
  protected:
      Singleton();
      Singleton(const Singleton&);
      Singleton& operator= (const Singleton&);
  };

The singleton is instantiated the first time you call the Instance() function (I think).

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Nov 06, 2005 at 16:10

monjardin: you are correct. The problem, however, is that you have absolutely no control over construction/destruction. Some prefer to have that control, particularly if there are cross-dependencies between singletons. If not, this actually is a good solution

3da8dff723c96426428d0fd0b9e8ec6c
0
Cybrid 101 Nov 06, 2005 at 21:31

Errrm , I’m sorry in my ignorance, but, what is exactly that operator overload doing?

Singleton& operator= (const Singleton&);

A8433b04cb41dd57113740b779f61acb
0
Reedbeta 167 Nov 06, 2005 at 22:38

That overloads the assignment operator, allowing you write statements like

Singleton a, b;
a = b;

However, I’m not sure why you would want that, since the whole idea of a singleton is that you only ever have one instance of it. And the constructors are protected anyway, so you wouldn’t be able to instanciate another copy of it yourself.

Cd577ee1cb56aa2ad5645b7daa0a2830
0
eddie 101 Nov 07, 2005 at 03:15

monjardin was making it protected so the compiler wouldn’t automatically roll one for you.

Cd577ee1cb56aa2ad5645b7daa0a2830
0
eddie 101 Nov 07, 2005 at 03:25

@monjardin

I usually do the following so that you don’t have to worry about doing a new/delete on your instance:

class Singleton 
  {
  public:
      static inline Singleton& Instance() {
            static Singleton instance;
            return instance;
      }
  protected:
      Singleton();
      Singleton(const Singleton&);
      Singleton& operator= (const Singleton&);
  };

The singleton is instantiated the first time you call the Instance() function (I think).

Actually, the singleton is instanced at compile time. When you create a static variable inside of a function, it’s initialized onto the data segment, so, as .oisyn says, you don’t actually have control over when it’s initialized.

That said, what you’ve got is basically a nice OO-based singleton-ish pattern above, so it’s not all bad, but the same thing could be achieved by creating a global and externing it.

Although, if letsay you were tracking access to people acquiring the instance, or doing some sort of locking on access, then the Singleton you have listed could be modified easily to accomplish this.

Where the Singleton really shines, as .oisyn already mentioned, is in controlling construction and deletion, and that’s why the Singleton pattern usually has memory allocation involved.

For example, if you have a class A that’s used as a singleton, as well as a class B, which is a singleton, you can ensure that any dependencies between the two are reconciled in an appropriate order, at runtime.

That is, things are constructed in the appopriate order, which you can’t guarantee with static function variables, or even global variables.

If I’m not making any sense, let me know and I’ll post up an example. Otherwise, I think I’ll limit my posts to a short story from now on in, instead of a novel. :)

22b3033832c5c699c856814b0cf80cb1
0
bladder 101 Nov 07, 2005 at 06:49

@eddie

Actually, the singleton is instanced at compile time. When you create a static variable inside of a function, it’s initialized onto the data segment, so, as .oisyn says, you don’t actually have control over when it’s initialized.

IIRC local static variables are initialized upon first use. So he will have control over when the singleton is initialized, but no idea when it gets deallocated.

Cd577ee1cb56aa2ad5645b7daa0a2830
0
eddie 101 Nov 07, 2005 at 07:37

Hrmm. Funny. I did my verification with a quick google search, and came up with the following:

http://www.phim.unibe.ch/comp_doc/c_manual/C/CONCEPT/storage_class.html#static

‘static’ can also be defined within a function. If this is done, the variable is initalised at compilation time and retains its value between calls. Because it is initialsed at compilation time, the initalistation value must be a constant. This is serious stuff - tread with care.

That said, in a quick test I’ve just done in a debugger, you’re right: it does get initialized on first use. Good to know.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Nov 07, 2005 at 10:22

eddie: you are talking about simple datatypes that can be initialized by simply putting the correct data in the data segment, as you say. Complex types that have constructors that need to be run will get initialized on first use, so when the Instance() function is first called. Or when you, for example, initialize an int with the result of something that is not known at compiletime (such as a function or a local variable)

#include <iostream>
#include <cstdlib>

int foo()
{
    std::cout << "in foo()" << std::endl;
    return rand();
}

void bar()
{
    std::cout << "in bar()" << std::endl;
    static int myInt = foo();
    std::cout << myInt << std::endl;
}

int main()
{
    std::cout << "first time:" << std::endl;
    bar();
    std::cout << "second time:" << std::endl;
    bar();
}

output:

first time:
in bar()
in foo()
<some random int>
second time:
in bar()
<the same random int as before>
3da8dff723c96426428d0fd0b9e8ec6c
0
Cybrid 101 Nov 07, 2005 at 13:09

@Reedbeta

That overloads the assignment operator, allowing you write statements like

Singleton a, b;
a = b;

However, I’m not sure why you would want that, since the whole idea of a singleton is that you only ever have one instance of it. And the constructors are protected anyway, so you wouldn’t be able to instanciate another copy of it yourself.

Thanks for the explanation Reedbeta

Cd577ee1cb56aa2ad5645b7daa0a2830
0
eddie 101 Nov 07, 2005 at 16:40

Ah. Thanks for the indepth explanatin .oisyn. :)

Things you don’t hit if you don’t use a particular language option often.

340bf64ac6abda6e40f7e860279823cb
0
_oisyn 101 Nov 07, 2005 at 16:58

@Reedbeta

That overloads the assignment operator, allowing you write statements like

Singleton a, b;
a = b;

However, I’m not sure why you would want that, since the whole idea of a singleton is that you only ever have one instance of it. And the constructors are protected anyway, so you wouldn’t be able to instanciate another copy of it yourself.

The whole point is making the assignment operator inaccessible by making it private/protected :). If you don’t declare an assignment operator, a default one get’s generated by the compiler that simply does a member-wise copy. Since you don’t want that on a singleton, you should declare it protected or private (I personally would go for private, as you’re not going to implement it anyway).

7895c52accea43ad88ba9ff90d2b9c6b
0
mseare 101 Nov 07, 2005 at 17:12

@.oisyn

The whole point is making the assignment operator inaccessible by making it private/protected :). If you don’t declare an assignment operator, a default one get’s generated by the compiler that simply does a member-wise copy. Since you don’t want that on a singleton, you should declare it protected or private (I personally would go for private, as you’re not going to implement it anyway).

I second this suggestion. Make it private.

6f0a333c785da81d479a0f58c2ccb203
0
monjardin 102 Nov 07, 2005 at 21:24

Private IS better IMHO. I was making as few changes to the original poster’s code as possible to avoid confusion. In practice, I typically just inherit from boost::noncopyable. That way it’s easier for me to understand what’s going on when I glance at the code.

.oisyn: The initialization issues are very good ones to bring up. I had to find them the hard way some time ago. :wallbash:
When I first learned of the singleton pattern I though it was the most convenient thing since sliced bread. It can definitely come back to bite you. The deallocation sequence is what really got me though.

Fdbdc4176840d77fe6a8deca457595ab
0
dk 158 Nov 08, 2005 at 00:24

Here’s an alternative method for implementing Singletons.