473,434 Members | 1,829 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,434 software developers and data experts.

C++ Singleton Pattern

Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;

// ...

private:
A() { /* ... */ }
};

A.cpp:

A A::theA;

rather than the complicated approaches I've
seen with the instance being allocated with "new"?

Dec 13 '06 #1
10 3298
wk****@yahoo.com wrote:
Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;

// ...

private:
A() { /* ... */ }
};

A.cpp:

A A::theA;

rather than the complicated approaches I've
seen with the instance being allocated with "new"?
Actually some of them are. Why do you say they aren't?

V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 13 '06 #2

wk****@yahoo.com wrote:
Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;

// ...

private:
A() { /* ... */ }
};

A.cpp:

A A::theA;
Whats stopying me from copying an instance of A?

int main()
{
A b(A::theA);
}
>
rather than the complicated approaches I've
seen with the instance being allocated with "new"?
How about:

#include <iostream>
#include <ostream>

template< typename T >
T& instance() // by reference only
{
static T t;
return t;
}

class A {
friend A& instance< A >();
A() { std::cout << "A()\n"; }
A(const A& copy) { std::cout << "copy A\n"; }
public:
~A() { std::cout << "~A()\n"; }
};

int main()
{
A& r_a = instance< A >();
// A a = instance< A >(); // error
std::cout << "&r_a = " << &r_a << std::endl;
A& r_b = instance< A >();
std::cout << "&r_b = " << &r_b << std::endl;
}

/*
A()
&r_a = 0x501fe0
&r_b = 0x501fe0
~A()
*/

Dec 13 '06 #3
wk****@yahoo.com a écrit :
Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;
private:
A() { /* ... */ }
};

A.cpp:

A A::theA;

rather than the complicated approaches I've
seen with the instance being allocated with "new"?
Your approach is dangerous, as you don't know when the object is
created. You are only able to successfully use it after you entered in
main(), and you should not use it after main() exit. It means that your
singleton cannot be used in static object construction and so on - note
that this might not be a problem in the end.

Meyer's singleton (the getInstance() function declares a static
variable and returns this variable) was probably what you got in mind -
the standard ensures that the static is constructed the first time you
entered in the function, so it is always valid - until you quit main()
(static objects order of destruction is well defined, but not easily
handled from the programmer point of view, so you'd better not use it
after you exit main()). Allocating the instance using new() in the
getInstance() function allows the same use as Meyer's singleton, but
the singleton is still valid until the memory is freed. If it is never
freed then you singleton is always valid.

* Your approach
class A
{
private:
static A theA;
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// time of construction is not known by the programmer
// time of destruction is not known by the programmer
A& instance() { return theA; }
};

* Meyer's approach
class A
{
private:
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// the instance will be created when you enter the
// function for the first time
// time of destruction is hard to tell from the programmer
// point of view
A& instance() { static A a; return a; }
};

* GoF approach:
class A
{
private:
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// the instance will be created when you enter the
// function for the first time
// the instance is never destroyed
A& instance() { static A *a = NULL; if (!a) a = new A(); return a; }
};

There's a very interesting discussion about singleton and their
possible implementation in the Modern C++ book of Andrei Alexandrescu.

Regards,

-- Emmanuel Deloget, Artware

Dec 13 '06 #4
Salt_Peter wrote:
wk****@yahoo.com wrote:
Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;

// ...

private:
A() { /* ... */ }
};

A.cpp:

A A::theA;

Whats stopying me from copying an instance of A?

int main()
{
A b(A::theA);
}
Yes, good point, I forgot the private undefined copy constructor.

rather than the complicated approaches I've
seen with the instance being allocated with "new"?

How about:

#include <iostream>
#include <ostream>

template< typename T >
T& instance() // by reference only
{
static T t;
return t;
}

class A {
friend A& instance< A >();
A() { std::cout << "A()\n"; }
A(const A& copy) { std::cout << "copy A\n"; }
public:
~A() { std::cout << "~A()\n"; }
};
So the reason for this is to avoid having, for classes with
all inline member functions (the exceptional case i would
think), a .cpp file that defines the single private instance?

Dec 13 '06 #5
Emmanuel Deloget wrote:
wk****@yahoo.com a écrit :
Why aren't "Singletons" done like this in C++:

A.hpp:

class A
{
public: static A theA;
private:
A() { /* ... */ }
};

A.cpp:

A A::theA;

rather than the complicated approaches I've
seen with the instance being allocated with "new"?

Your approach is dangerous, as you don't know when the object is
created. You are only able to successfully use it after you entered in
main(), and you should not use it after main() exit. It means that your
singleton cannot be used in static object construction and so on - note
that this might not be a problem in the end.

Meyer's singleton (the getInstance() function declares a static
variable and returns this variable) was probably what you got in mind -
the standard ensures that the static is constructed the first time you
entered in the function, so it is always valid - until you quit main()
(static objects order of destruction is well defined, but not easily
handled from the programmer point of view, so you'd better not use it
after you exit main()). Allocating the instance using new() in the
getInstance() function allows the same use as Meyer's singleton, but
the singleton is still valid until the memory is freed. If it is never
freed then you singleton is always valid.

* Your approach
class A
{
private:
static A theA;
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// time of construction is not known by the programmer
// time of destruction is not known by the programmer
A& instance() { return theA; }
};

* Meyer's approach
class A
{
private:
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// the instance will be created when you enter the
// function for the first time
// time of destruction is hard to tell from the programmer
// point of view
A& instance() { static A a; return a; }
};
My understanding is that the standard allows local statics to
be initialized any time before the line of executable code
following their definition is executed. So I don't see how
this addresses the order-of-intialization problem.
* GoF approach:
class A
{
private:
A() { }
~A() { }
A(const A&) { }
A& operator=(const A&);
public:
// the instance will be created when you enter the
// function for the first time
// the instance is never destroyed
A& instance() { static A *a = NULL; if (!a) a = new A(); return a; }
};
I dislike this because of the added overhead to every single access
to the instance.

(Insert by reference here any of the long heated threads about
whether minor optimizations are worth it.)

The are also cases where the fact that the instance is not
destroyed can be a problem. If the instance sets some
sort of lock flag in a file or in a shared memory segment,
the file will close/segment will detach on program exit,
but the lock flag won't be cleared.

Dec 13 '06 #6
wk****@yahoo.com wrote:
[..]
My understanding is that the standard allows local statics to
be initialized any time before the line of executable code
following their definition is executed. So I don't see how
this addresses the order-of-intialization problem.
Your understanding is incorrect. The local statics are initialised
when the control passes their initialisation for the first time.
[..]
V
--
Please remove capital 'A's when replying by e-mail
I do not respond to top-posted replies, please don't ask
Dec 13 '06 #7
Emmanuel Deloget wrote:
.....
// the instance will be created when you enter the
// function for the first time
// the instance is never destroyed
A& instance() { static A *a = NULL; if (!a) a = new A(); return a; }
// is this not the same ?
A& instance() { static A *a = new A(); return *a; }

With gcc, this is also thread-safe.
Dec 14 '06 #8
Victor Bazarov wrote:
wk****@yahoo.com wrote:
[..]
My understanding is that the standard allows local statics to
be initialized any time before the line of executable code
following their definition is executed. So I don't see how
this addresses the order-of-intialization problem.

Your understanding is incorrect. The local statics are initialised
when the control passes their initialisation for the first time.
....

Since you likely know the case-law on this much better than
me, I will take your word on this. Looking at Draft 98, 6.7-4
seems to unnecessary go around the block a few times.
Why not just say local statics are intialized when control
passes them, undefined value before initialization, and let
the as-if rule allow for optimized early initialization?

The implication of this is that the compiler has to generate
a hidden static flag to prevent re-initialization, and that flag
has to be checked every time control passes the local static
definition.

Dec 14 '06 #9
wk****@yahoo.com wrote:
....
The implication of this is that the compiler has to generate
a hidden static flag to prevent re-initialization, and that flag
has to be checked every time control passes the local static
definition.
Wait until you read about the order of destruction.
Dec 14 '06 #10
wk****@yahoo.com wrote:
Victor Bazarov wrote:
>wk****@yahoo.com wrote:
>>[..]
My understanding is that the standard allows local statics to
be initialized any time before the line of executable code
following their definition is executed. So I don't see how
this addresses the order-of-intialization problem.
Your understanding is incorrect. The local statics are initialised
when the control passes their initialisation for the first time.
...

Since you likely know the case-law on this much better than
me, I will take your word on this. Looking at Draft 98, 6.7-4
seems to unnecessary go around the block a few times.
Why not just say local statics are intialized when control
passes them, undefined value before initialization, and let
the as-if rule allow for optimized early initialization?

The implication of this is that the compiler has to generate
a hidden static flag to prevent re-initialization, and that flag
has to be checked every time control passes the local static
definition.
[Offtopic]
Standard only defines the behavior of local static variables. But how
it's achieved is highly implementation specific. In the real world,
local static variables are implemented like global static variables
(with/wo slight difference in the segments they initially occupy), they
have guaranteed memory storage by compiler. Linker looks them up and
generates relocatable code in the end.

Fei
Dec 15 '06 #11

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

Similar topics

3
by: Alicia Roberts | last post by:
Hello everyone, I have been researching the Singleton Pattern. Since the singleton pattern uses a private constructor which in turn reduces extendability, if you make the Singleton Polymorphic...
4
by: Neil Zanella | last post by:
Hello, I would be very interested in knowing how the following C++ multi-instance singleton (AKA Borg) design pattern based code snippet can be neatly coded in Python. While there may be...
1
by: Richard A. DeVenezia | last post by:
foo() generates elements with event handlers that invoke foo function properties. Is this an abhorrent or misthought pattern ? It allows just the one occurence of identifier /foo/ to be changed...
3
by: Alicia Roberts | last post by:
Hello everyone, I have been researching the Singleton Pattern. Since the singleton pattern uses a private constructor which in turn reduces extendability, if you make the Singleton Polymorphic...
11
by: Daniel Billingsley | last post by:
Let's say I'm writing a business app and I want there to be only one instance of the Customer object for each particular customer (representing a database record) being edited. Would it be...
21
by: Sharon | last post by:
I wish to build a framework for our developers that will include a singleton pattern. But it can not be a base class because it has a private constructor and therefore can be inherit. I thought...
13
by: Robert W. | last post by:
At the beginning of my C# days (about 6 months ago) I learned about the Singleton pattern and implemented for Reference data, such as the kind that appears in an Options dialog box. My Singleton...
2
by: Kevin Newman | last post by:
I have been playing around with a couple of ways to add inheritance to a JavaScript singleton pattern. As far as I'm aware, using an anonymous constructor to create a singleton does not allow any...
3
by: dischdennis | last post by:
Hello List, I would like to make a singleton class in python 2.4.3, I found this pattern in the web: class Singleton: __single = None def __init__( self ): if Singleton.__single: raise...
3
weaknessforcats
by: weaknessforcats | last post by:
Design Pattern: The Singleton Overview Use the Singleton Design Pattern when you want to have only one instance of a class. This single instance must have a single global point of access. That...
1
by: nemocccc | last post by:
hello, everyone, I want to develop a software for my android phone for daily needs, any suggestions?
1
by: Sonnysonu | last post by:
This is the data of csv file 1 2 3 1 2 3 1 2 3 1 2 3 2 3 2 3 3 the lengths should be different i have to store the data by column-wise with in the specific length. suppose the i have to...
0
by: Hystou | last post by:
There are some requirements for setting up RAID: 1. The motherboard and BIOS support RAID configuration. 2. The motherboard has 2 or more available SATA protocol SSD/HDD slots (including MSATA, M.2...
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...
1
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
agi2029
by: agi2029 | last post by:
Let's talk about the concept of autonomous AI software engineers and no-code agents. These AIs are designed to manage the entire lifecycle of a software development project—planning, coding, testing,...
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...
0
by: conductexam | last post by:
I have .net C# application in which I am extracting data from word file and save it in database particularly. To store word all data as it is I am converting the whole word file firstly in HTML and...
0
by: TSSRALBI | last post by:
Hello I'm a network technician in training and I need your help. I am currently learning how to create and manage the different types of VPNs and I have a question about LAN-to-LAN VPNs. The...

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.