473,396 Members | 2,011 Online
Bytes | Software Development & Data Engineering Community
Post Job

Home Posts Topics Members FAQ

Join Bytes to post your question to a community of 473,396 software developers and data experts.

A question about initilization of a static member

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.

Mar 22 '07 #1
9 1498
On Mar 22, 12:15 pm, "wizwx" <wiz...@gmail.comwrote:
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-lit...tml#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<Fooa friend, etc.
public:
void Bar();
};

typedef Singleton<FootheFoo;

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

Mar 22 '07 #2
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

--
SasQ
Mar 22 '07 #3
On Mar 22, 1:55 pm, SasQ <s...@go2.plwrote:
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
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

Mar 22 '07 #4
On Mar 22, 10:55 am, SasQ <s...@go2.plwrote:
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
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 ?
>
--
SasQ

Mar 22 '07 #5
Dnia Thu, 22 Mar 2007 11:41:05 -0700, mlimber napisał(a):
>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
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

--
SasQ
Mar 22 '07 #6
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
>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 ?
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

--
SasQ
Mar 22 '07 #7
Dnia Fri, 23 Mar 2007 00:07:29 +0100, SasQ napisał(a):

Oh, and there is another one fot the following:
>>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 ?
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.

--
SasQ
Mar 22 '07 #8
On Mar 22, 6:48 pm, SasQ <s...@go2.plwrote:
Dnia Thu, 22 Mar 2007 11:41:05 -0700, mlimber napisał(a):
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

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

Mar 23 '07 #9
On Mar 22, 7:07 pm, SasQ <s...@go2.plwrote:
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 ;)
And see my response elsethread.
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 ?

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

Mar 23 '07 #10

This thread has been closed and replies have been disabled. Please start a new discussion.

Similar topics

11
by: Roger Leigh | last post by:
The C++ book I have to hand (Liberty and Horvath, Teach yourself C++ for Linux in 21 Days--I know there are better) states that "static member functions cannot access any non-static member...
5
by: vsnadagouda | last post by:
Hello All, I am looking for some way to delay the global variable initilization. To make myself more clear, here is a simple example: +++++++++++++++++++++++++++++++++++++++++++++++++++++++++...
8
by: Yong W | last post by:
if A and B are Class type, what's mean about the next sentence? " int A::*B::*pMember; " And how to use this pointer ? we assume A and B's definition is: class A { int a;
9
by: luc.holtkamp | last post by:
I have a simple question: A static member can be called with the scope operator: class A { public: A (int a) : m_a (a) {} static A fromInt (int x) { return A (x); } private: int m_a;
4
by: Jess | last post by:
Hello, I tried several books to find out the details of object initialization. Unfortunately, I'm still confused by two specific concepts, namely default-initialization and...
4
by: Josefo | last post by:
Hello, is someone so kind to tell me why I am getting the following errors ? vector_static_function.c:20: error: expected constructor, destructor, or type conversion before '.' token...
2
by: .rhavin grobert | last post by:
i have (do try to have?) the following... & = breakpoints in debugger // ---------------------------------------------------------------- // cx.h class CX { public: CX(CX* pcx = NULL);...
13
by: yanlinlin82 | last post by:
I'd like to write all code of a class in only header file. But when there is any static member varia ble, I have to define it in cpp file, not the header file. Otherwise, the static member variable...
10
by: JosephLee | last post by:
In Inside C++ object Model, Lippman said there are four cases in which compile will sythesize a default constructor to initialize the member variables if the constructor is absent: 1. there is a...
0
by: emmanuelkatto | last post by:
Hi All, I am Emmanuel katto from Uganda. I want to ask what challenges you've faced while migrating a website to cloud. Please let me know. Thanks! Emmanuel
0
BarryA
by: BarryA | last post by:
What are the essential steps and strategies outlined in the Data Structures and Algorithms (DSA) roadmap for aspiring data scientists? How can individuals effectively utilize this roadmap to progress...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
0
marktang
by: marktang | last post by:
ONU (Optical Network Unit) is one of the key components for providing high-speed Internet services. Its primary function is to act as an endpoint device located at the user's premises. However,...
0
by: Hystou | last post by:
Most computers default to English, but sometimes we require a different language, especially when relocating. Forgot to request a specific language before your computer shipped? No problem! You can...
0
Oralloy
by: Oralloy | last post by:
Hello folks, I am unable to find appropriate documentation on the type promotion of bit-fields when using the generalised comparison operator "<=>". The problem is that using the GNU compilers,...
0
by: Hystou | last post by:
Overview: Windows 11 and 10 have less user interface control over operating system update behaviour than previous versions of Windows. In Windows 11 and 10, there is no way to turn off the Windows...
0
tracyyun
by: tracyyun | last post by:
Dear forum friends, With the development of smart home technology, a variety of wireless communication protocols have appeared on the market, such as Zigbee, Z-Wave, Wi-Fi, Bluetooth, etc. Each...
0
isladogs
by: isladogs | last post by:
The next Access Europe User Group meeting will be on Wednesday 1 May 2024 starting at 18:00 UK time (6PM UTC+1) and finishing by 19:30 (7.30PM). In this session, we are pleased to welcome a new...

By using Bytes.com and it's services, you agree to our Privacy Policy and Terms of Use.

To disable or enable advertisements and analytics tracking please visit the manage ads & tracking page.