Singleton Pattern

18 replies to this topic

#1Cybrid

New Member

• Members
• 19 posts

Posted 05 November 2005 - 01:08 PM

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.

/*Books, days and ways, gives men wisdom*/
HUMAN KNOWLEDGE BELONGS TO THE WORLD

#2roel

Senior Member

• Members
• 698 posts

Posted 05 November 2005 - 01:28 PM

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.

#3hauptman

New Member

• Members
• 8 posts

Posted 05 November 2005 - 02:30 PM

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.

#4Cybrid

New Member

• Members
• 19 posts

Posted 05 November 2005 - 03:24 PM

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

Thanks to you both :happy:
/*Books, days and ways, gives men wisdom*/
HUMAN KNOWLEDGE BELONGS TO THE WORLD

#5monjardin

Senior Member

• Members
• 1033 posts

Posted 06 November 2005 - 02:27 PM

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).
monjardin's JwN Meter (1,2,3,4,5,6):
|----|----|----|----|----|----|----|----|----|----|
*

#6.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 06 November 2005 - 04:10 PM

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
-
Currently working on: the 3D engine for Tomb Raider.

#7Cybrid

New Member

• Members
• 19 posts

Posted 06 November 2005 - 09:31 PM

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

Singleton& operator= (const Singleton&);
/*Books, days and ways, gives men wisdom*/
HUMAN KNOWLEDGE BELONGS TO THE WORLD

#8Reedbeta

DevMaster Staff

• 5310 posts
• LocationSanta Clara, CA

Posted 06 November 2005 - 10:38 PM

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.
reedbeta.com - developer blog, OpenGL demos, and other projects

#9eddie

Senior Member

• Members
• 751 posts

Posted 07 November 2005 - 03:15 AM

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

#10eddie

Senior Member

• Members
• 751 posts

Posted 07 November 2005 - 03:25 AM

monjardin said:

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. :)

DevMaster Staff

• Members
• 1057 posts

Posted 07 November 2005 - 06:49 AM

eddie said:

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.

#12eddie

Senior Member

• Members
• 751 posts

Posted 07 November 2005 - 07:37 AM

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

http://www.phim.unib...ass.html#static

Quote

'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.

#13.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 07 November 2005 - 10:22 AM

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>

-
Currently working on: the 3D engine for Tomb Raider.

#14Cybrid

New Member

• Members
• 19 posts

Posted 07 November 2005 - 01:09 PM

Reedbeta said:

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
/*Books, days and ways, gives men wisdom*/
HUMAN KNOWLEDGE BELONGS TO THE WORLD

#15eddie

Senior Member

• Members
• 751 posts

Posted 07 November 2005 - 04:40 PM

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

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

#16.oisyn

DevMaster Staff

• Moderators
• 1842 posts

Posted 07 November 2005 - 04:58 PM

Reedbeta said:

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).
-
Currently working on: the 3D engine for Tomb Raider.

#17mseare

New Member

• Members
• 3 posts

Posted 07 November 2005 - 05:12 PM

.oisyn said:

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.

#18monjardin

Senior Member

• Members
• 1033 posts

Posted 07 November 2005 - 09:24 PM

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.

#19Dia

DevMaster Staff