Singleton usage

M

Manuel

Consider the classic singleton (from Thinking in C++):
-----------------------------------------------------
//: C10:SingletonPattern.cpp
#include <iostream>
using namespace std;

class Singleton {
static Singleton s;
int i;
Singleton(int x) : i(x) { }
Singleton& operator=(Singleton&); // Disallowed
Singleton(const Singleton&); // Disallowed
public:
static Singleton& instance() { return s; }
int getValue() { return i; }
void setValue(int x) { i = x; }
};
-----------------------------------------------------

I've read this type of singleton is often used to store the global
variables, but I don't have found a clear explanation.

An example:

if, in file main.cpp, I write

Singleton Singleton::s(47);
Singleton& s = Singleton::instance();

and, in foo1.cpp, I write

Singleton& s1 = Singleton::instance();

and in foo2.cpp I write

Singleton& s2 = Singleton::instance();


these instances (s, s1 and s2) are the same object, so all methods and
properties are shared???? Because Singleton::s is static, I suppose yes,
but I'm not sure...

thx,

Manuel
 
V

Victor Bazarov

Manuel said:
Consider the classic singleton (from Thinking in C++):
-----------------------------------------------------
//: C10:SingletonPattern.cpp
#include <iostream>
using namespace std;

class Singleton {
static Singleton s;
int i;
Singleton(int x) : i(x) { }
Singleton& operator=(Singleton&); // Disallowed
Singleton(const Singleton&); // Disallowed
public:
static Singleton& instance() { return s; }
int getValue() { return i; }
void setValue(int x) { i = x; }
};
-----------------------------------------------------

I've read this type of singleton is often used to store the global
variables, but I don't have found a clear explanation.

An example:

if, in file main.cpp, I write

Singleton Singleton::s(47);
Singleton& s = Singleton::instance();

and, in foo1.cpp, I write

Singleton& s1 = Singleton::instance();

and in foo2.cpp I write

Singleton& s2 = Singleton::instance();


these instances (s, s1 and s2) are the same object,

They are all _references_, and they do _refer_ to the same object, yes.
so all methods and
properties are shared????

Since they _refer_ to the same object, all "properties" are that of the
object to which they refer.
Because Singleton::s is static, I suppose
yes, but I'm not sure...

Yes. The implementation makes sure that (a) only one instance of that
class can ever be created in the program and (b) any time somebody wants
to use it, they are forced to use a _reference_ to that instance. That
is essentially the definition of a singleton.

V
 
M

Manuel

Victor said:
Yes. The implementation makes sure that (a) only one instance of that
class can ever be created in the program and (b) any time somebody wants
to use it, they are forced to use a _reference_ to that instance. That
is essentially the definition of a singleton.

Thank you very much!

Manuel
 
M

Manuel

Victor said:
Yes. The implementation makes sure that [...]


Another question.
The example in "Thinking in C++" is:
----------------------------------------
Singleton Singleton::s(47);

int main() {
Singleton& s = Singleton::instance();
cout << s.getValue() << endl;
Singleton& s2 = Singleton::instance();
s2.setValue(9);
cout << s.getValue() << endl;
} ///:~
----------------------------------------

Any particular reason the singleton init is out of main()?
It should be global even if declared into a function, right?

thx,

Manuel
 
V

Victor Bazarov

Manuel said:
Victor said:
Yes. The implementation makes sure that [...]


Another question.
The example in "Thinking in C++" is:
----------------------------------------
Singleton Singleton::s(47);

int main() {
Singleton& s = Singleton::instance();
cout << s.getValue() << endl;
Singleton& s2 = Singleton::instance();
s2.setValue(9);
cout << s.getValue() << endl;
} ///:~

That's the requirement for static data members of any class.
If they are to be defined, they must be defined at the namespace
scope.

V
 
A

Axter

Manuel said:
Consider the classic singleton (from Thinking in C++):
-----------------------------------------------------
//: C10:SingletonPattern.cpp
#include <iostream>
using namespace std;

class Singleton {
static Singleton s;
int i;
Singleton(int x) : i(x) { }
Singleton& operator=(Singleton&); // Disallowed
Singleton(const Singleton&); // Disallowed
public:
static Singleton& instance() { return s; }
int getValue() { return i; }
void setValue(int x) { i = x; }
};

Be aware, that if the above singleton is called from another global
object during initialization that's in a different translation unit,
than it can, and most likely will fail.

There's no garantee for the order of initialization of global complex
objects located in different translation units.
See following links:
http://www.informit.com/guides/content.asp?g=cplusplus&seqNum=212&rl=1

And read SECOND paragraph in the following link:
http://www.codeguru.com/cpp/tic/tic0114.shtml


A safer method would be the following:
class Singleton {
static const int m_MySingletonParam;
int i;
Singleton(int x) : i(x) { }
Singleton& operator=(Singleton&); // Disallowed
Singleton(const Singleton&); // Disallowed
public:
static Singleton& instance()
{
static Singleton s(m_MySingletonParam);
return s;
}
int getValue() { return i; }
void setValue(int x) { i = x; }
};

//In one CPP file
const int Singleton::m_MySingletonParam = 123;


The above method is garanteed to work, because POD types are garanteed
to be initailized before non-POD types. And local static variables are
garanteed to be initialized when the function is called.
So you can safely call the above Singleton from any other global
object's constructor, regardless of the translation unit.

If it's possible that the singlton will be called after main() exits,
then you should create the object via new, to make sure it doesn't get
destroyed before othe global object's destructs are called.
static Singleton& instance()
{
static Singleton *s = new Singleton (m_MySingletonParam);
return *s;
}
 
R

roberts.noah

Manuel said:
Victor said:
Yes. The implementation makes sure that [...]


Another question.
The example in "Thinking in C++" is:
----------------------------------------
Singleton Singleton::s(47);

int main() {
Singleton& s = Singleton::instance();
cout << s.getValue() << endl;
Singleton& s2 = Singleton::instance();
s2.setValue(9);
cout << s.getValue() << endl;
} ///:~

Since s is a static inside of Singleton it has to be initialized. All
static variables must be initialized exactly once or you will get a
linker error (because the declaration is just that and the variable was
never defined).

Try it and see...
 

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

No members online now.

Forum statistics

Threads
473,965
Messages
2,570,148
Members
46,710
Latest member
FredricRen

Latest Threads

Top