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

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

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

0
101 Nov 05, 2005 at 15:24

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

Thanks to you both :happy:

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

0
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

0
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&);

0
165 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.

0
101 Nov 07, 2005 at 03:15

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

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

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

0
101 Nov 07, 2005 at 07:37

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

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

0
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>

0
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

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

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

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

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

0
157 Nov 08, 2005 at 00:24

Here’s an alternative method for implementing Singletons.