A question about initilization of a static member

W

wizwx

There are two typical implementations of a singleton. The first one
is
to use a static pointer
class Singleton {
static Singleton * pSingleton;
public:
static Singleton * instance() {
if(pSingleton==NULL)
pSingleton = new Singleton;
return pSingleton;
}
// ....

};
Singleton * Singleton::pSingleton;

The other is to use a function static (also known as Meyer's
singleton)
class Singleton {
public:
static Singleton& instance() {
static _singleton;
return _singleton;
}
// ....
};

However I just noticed a third one from Bruce Eckel's "Thinking in C+
+" vol. 2, pp 620:
class Singleton {
static Singleton s;
public:
static Singleton& instance() {
return s;
}
// ....
};
Singleton Singleton::s;


It is interesting that a static member of itself (Singleton) is
declared inside
the Singleton class. I tested the code in linux, and g++
compiled it successfully.

My question is: How could this happen? How could a class have a member
of the type of itself? This is obviously not valid if there is no
keyword static. However, what features of the keyword
"static" make this feasible?


Thank you for any comments.
 
M

mlimber

There are two typical implementations of a singleton. The first one
is
to use a static pointer
class Singleton {
static Singleton * pSingleton;
public:
static Singleton * instance() {
if(pSingleton==NULL)
pSingleton = new Singleton;
return pSingleton;
}
// ....

};

Singleton * Singleton::pSingleton;

The other is to use a function static (also known as Meyer's
singleton)
class Singleton {
public:
static Singleton& instance() {
static _singleton;
return _singleton;
}
// ....

};

However I just noticed a third one from Bruce Eckel's "Thinking in C+
+" vol. 2, pp 620:
class Singleton {
static Singleton s;
public:
static Singleton& instance() {
return s;
}
// ....};

Singleton Singleton::s;

It is interesting that a static member of itself (Singleton) is
declared inside
the Singleton class. I tested the code in linux, and g++
compiled it successfully.

My question is: How could this happen? How could a class have a member
of the type of itself? This is obviously not valid if there is no
keyword static. However, what features of the keyword
"static" make this feasible?

Thank you for any comments.

There are several other spins on singletons discussed in _Modern C++
Design_. I'd avoid Eckel's because of potential problems with the
static initialization order fiasco (see http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.12).
You can also templatize Meyers's to make it easier to use (IMHO):

template<class T>
class Singleton
{
public:
static T& Instance()
{
static T t;
return t;
}
};

class Foo
{
// Could make ctor private and
// Singleton<Foo> a friend, etc.
public:
void Bar();
};

typedef Singleton<Foo> theFoo;

void Baz()
{
theFoo::Instance().Bar();
}

Anywho, static members don't enter into the calculation of the size of
the class you're declaring or of parameters passed to its functions,
so the compiler doesn't need to have anymore than a forward
declaration until the class' actual definition (cf.
http://gotw.ca/publications/mill04.htm). This example illustrates:

class A; // Forward declaration
class B // Acts like a forward declaration
{
static A a;
static B b;

A* pa;
B* ba;

A Foo();
B Bar();
};

class A {}; // Definition

A B::a;
B B::b;

Note that the class' full definitions aren't needed until B's static
members are actually defined.

Cheers! --M
 
S

SasQ

Dnia Thu, 22 Mar 2007 09:15:02 -0700, wizwx napisa³(a):
There are two typical implementations of a singleton.
The first one is to use a static pointer
class Singleton {
static Singleton * pSingleton;
public:
static Singleton * instance() {
if(pSingleton==NULL)
pSingleton = new Singleton;
return pSingleton;
}
// ....
};
Singleton * Singleton::pSingleton;

This is not a good solution because:
1. Where do you call delete on that singleton object created
with operator "new"? It will cause a memory leak ;P
2. Returning pointer to internal data exposes it for
everyone to call "delete" on it and break everything :p
 
M

mlimber

Dnia Thu, 22 Mar 2007 09:15:02 -0700, wizwx napisa³(a):


This is not a good solution because:
1. Where do you call delete on that singleton object created
with operator "new"? It will cause a memory leak ;P

Though in practice, the OS will usually clean it up for you, and in
environments where it won't (e.g., the embedded world), it often still
doesn't matter since the program doesn't end except by losing power.

Cheers! --M
 
A

amparikh

Dnia Thu, 22 Mar 2007 09:15:02 -0700, wizwx napisa³(a):


This is not a good solution because:
1. Where do you call delete on that singleton object created
with operator "new"? It will cause a memory leak ;P

Look for mlimber's answer on this one.
2. Returning pointer to internal data exposes it for
everyone to call "delete" on it and break everything :p

What if the destructor is made private ?
 
S

SasQ

Dnia Thu, 22 Mar 2007 11:41:05 -0700, mlimber napisa³(a):
Though in practice, the OS will usually clean it up for you

a) Which OS? Every? What makes you so sure? ;J
b) Even if the memory will be freed upon a program end, that is
still not a good solution, because if you will not call "delete"
on that object, its destructor won't be called. You don't know
what would destructor do - it might free some memory resources,
it may write data to a file etc., so if you don't call "delete"
on that object, your users will stick you on a pole for
losing their precious data :p
and in environments where it won't (e.g., the embedded world),
it often still doesn't matter since the program doesn't end
except by losing power.

In programming it's always wrong using that kind of excuses. And
my friend use to say that presumption is a mother of all fuckups ;J
 
S

SasQ

Dnia Thu, 22 Mar 2007 13:54:19 -0700, amparikh napisa³(a):
Look for mlimber's answer on this one.

Look for my answer to milber on this one ;)
Memory might [or might not] be freed upon a program end,
but destructors won't be called. Imagine a destructor which
saves closing document to a file, and you'll get the base ;J
What if the destructor is made private ?

Then you won't be able to call it anyhow but from the inside
of a class itself. If it will be possible to create object,
which might not be possible to destroy, the compiler won't
allow you to create it at all. It will say you that destructor
is private in a context of object definition and construction.
Even if it might be possible to create object dynamically using
operator "new", you are getting into trouble, because still you
won't be able to call "delete" to make destructor into run.
Your compiler should warn you that you're making something
very bad and erroneous [mine does].
So, your private constructor will NOT solve the problem - it
will only push it for later.
It is baaad, baaad idea! :p You should think, not guess! :p
You better listen experienced programmers instead of thinking
about nasty work-arounds to what you made ;P
 
S

SasQ

Dnia Fri, 23 Mar 2007 00:07:29 +0100, SasQ napisa³(a):

Oh, and there is another one fot the following:

Issue with calling "delete" on returned pointer to singleton
is not the only flaw of this solution. Even if you disallow
calling delete, you are still exposing the internal object
for external users of a class, and they would be able to
call not only a "delete", but ANY function from its public
interface. Singleton instance is made private for a reason,
and exposing it to the external world through a pointer
is breaking the encapsulation. By doing that, you are simply
loosing control over the managed singleton object.
 
M

mlimber

Dnia Thu, 22 Mar 2007 11:41:05 -0700, mlimber napisa³(a):



a) Which OS? Every? What makes you so sure? ;J

Windows and Unix, which I'd guess covers about 99% of users.
b) Even if the memory will be freed upon a program end, that is
still not a good solution, because if you will not call "delete"
on that object, its destructor won't be called. You don't know
what would destructor do - it might free some memory resources,
it may write data to a file etc., so if you don't call "delete"
on that object, your users will stick you on a pole for
losing their precious data :p

In general, of course I'd advocate a singleton pattern with automatic
cleanup (like the Meyers singleton), but I'm just saying that this
type of thing is not necessarily a dangerous or even meaningful type
of *memory leak*, which is all you mentioned in your first post.
In programming it's always wrong using that kind of excuses. And
my friend use to say that presumption is a mother of all fuckups ;J

No it isn't. Some objects don't have meaningful destruction semantics,
and the destruction of others just doesn't matter in some circs.
Nonetheless, I'd still recommend a different type of singleton for
general consumption.

Cheers! --M
 
M

mlimber

Dnia Thu, 22 Mar 2007 13:54:19 -0700, amparikh napisa³(a):


Look for my answer to milber on this one ;)

And see my response elsethread.
Then you won't be able to call it anyhow but from the inside
of a class itself.

....unless the singleton class is made a friend, which is not an
uncommon practice (see Alexandrescu's _Modern C++ Design_, chapter 6).
It is baaad, baaad idea! :p You should think, not guess! :p
You better listen experienced programmers instead of thinking
about nasty work-arounds to what you made ;P

If so, I'd recommend that you'd better listen to programmers more
experienced than yourself, like Alexandrescu.

Cheers! --M
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,968
Messages
2,570,149
Members
46,695
Latest member
StanleyDri

Latest Threads

Top