Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

Singleton

Hello,

I have the following Singleton code :-

#include <iostream>

using namespace std;

class Singleton
{
private:
static bool instanceFlag;
static Singleton *single;

Singleton()
{
//private constructor
}
public:
static Singleton* getInstance()
{
cout << "instanceFlag = " << instanceFlag << endl;
if(!instanceFlag)
{
single = new Singleton();
instanceFlag = true;
return single;
}
else
{
return single;
}
}

void method()
{
cout << "\tMethod of the singleton class" << endl << endl;
}

~Singleton()
{
instanceFlag = false;
}
};

bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;

int main()
{
Singleton *sc1,*sc2;

sc1 = Singleton::getInstance();
sc1->method();
sc2 = Singleton::getInstance();
sc2->method();
return 0;
}

I understand most of the code, however, can someone please explain the highlited lines ? Is this a C++ way to initialise static private members without having a setValues() function ?
Can we write a setValues() function for static members ?
Also, why do we need to have static members here ? The Java implementation also uses static but much more stright forward to understand :-

public class Singleton {
/**
* The constructor could be made private
* to prevent others from instantiating this class.
* But this would also make it impossible to
* create instances of Singleton subclasses.
*/
protected Singleton() {
// ...
}


/**
* A handle to the unique Singleton instance.
*/
static private Singleton _instance = null;

/**
* @return The unique instance of this class.
*/
static public Singleton instance() {
if(null == _instance) {
_instance = new Singleton();
}
return _instance;
}


/. ...additional methods omitted...
}

The other thing, Singleton means I can only create one instance of. How can I prove that this works ?
[2429 byte] By [ami] at [2007-11-11 10:13:11]
# 1 Re: Singleton
bool Singleton::instanceFlag = false;
Singleton* Singleton::single = NULL;

These are definitions cum intializers (which aren't really necessary here since static data members are zero initialized by default anyway) of static data members. Unlike in Java, C++ requires that static data members be declared in the class, and have separate definitions outside the class. The main reason for the difference between C++ and Java is that C++ uses header files and .cpp files, so the definitions of a static members should be in the .cpp file, to avoid multiple instances. In java you don't have .h files nor object files nor exe files so its object model is radically different.

You cannot have a setValues function for static data members because such a function would require the instantiation of an object, for which the setValues call is made. In other words, you can't call a function before you have an object, but you need to initialize the static members before you have an object... it's possible to define a static member function to take care of static data members but since static data members are automatically zero initialized before the program even starts, you won't find setValues very useful anyway.

Finally, you need static data members here because the singleton object can be accessed even when there isn't a single object of class Singleton.

Singleton* p= Singleton::getInstance();

The static member function getInstance is called even when there is no object of type Singleton yet. This is possible only if getIsntance is a static member function. And static member functions can only access static data members, never non-static data members.

Java and C++ use more or less the same implementation for the Singleton desin pattern, except for language specific differences.
Danny at 2007-11-11 20:59:10 >
# 2 Re: Singleton
Only one question: Who will destroy the Singleton object? (Or to be more precise, who will call it's destructor?)
dcwexter at 2007-11-11 21:00:17 >
# 3 Re: Singleton
Good question;)
The Singleton class needs to define a static member function called destroy() that deletes the static pointer to the Singleton.

class Singleon
{
//..
static void destroy() { delete pinstance; }
};

When the program doesn't need the singleton object anymore, it must call Singleton::destroy() explicitly.
That's why i dislike singletons btw. In many cases, simple smart pointers can do the job and I think that the importance and usefulness of singleton has been overstated.
Danny at 2007-11-11 21:01:15 >
# 4 Re: Singleton
Especially when people try to preserve space with it. :eek: I usually use auto_ptr to ensure destructor is called, but there are some other options. For example, in single threaded world (somewhat simplified condition), instance function could look like this

#include <iostream>

using namespace std;

class Singleton
{
private:
Singleton()
{
// here we allocate some operating system resources
// calling api functions (which don't have to have anything
// with memory allocations, e.g. sockets, mutexes...)
}

~Singleton()
{
// here we release resources
}

public:
static Singleton &getInstance()
{
static Singleton instance;
return instance;
}

// here are some public methods
}

Here we don't have any influence on destruction order, but at least it should happen automatically.
dcwexter at 2007-11-11 21:02:15 >
# 5 Re: Singleton
Your class isn't exactly a Singletone but an ordinary RAII class.
More about RAII here: http://www.dev-archive.com/dev-archive/LegacyLink/9395

The main difference between Singleton and RAII is that the Singleton class can't have mutiple instances. You obtain the resource by calling a static member function, without ever instantiating the class that creates the resource. According to the origial documentation, a singleton's purpose is to "provide a single method of accessing a resource", which means that you can't have several instances of a Singleton. Similarly, you release the resource explicitly by calling destroy.
You can't rely on the destructor to automatically release the resource because if the user never instantiated the Singleton as a local automatic object, the destructor will never get called (unless you call it explicitly, but what's the point?) A Signgleton class doesn't have a constructor (or it's declared private) to ensure that users can't create multiple objects.
RAII classes can have multiple instances. For example, I can create two shared_ptr objects that point to the same resource. Secondly, RAII classes have nonstatic member functions for accessing the resource.
Danny at 2007-11-11 21:03:20 >
# 6 Re: Singleton
I'm sorry, but I don't see what's missing in my implementation. It has private constructor and destructor (well, it's just sample implementations, so copy constructor and assignment operator are missing). And has single access point, which is getInstance function.

Just curious... :confused:
dcwexter at 2007-11-11 21:04:25 >
# 7 Re: Singleton
Sorry, you went for the value object solution instead of using a static pointer and I missed this crucial part. Some pattern books gave this example in the late 1990s as an alternative to the heap allocation approach, but it was criticized for its lack of thread safety. If this class is used in a strictly single threaded environment, as you said, it's fine (so long as no one accesses instance after its destruction of course). A tiny nit: the assignment operator and the copy ctor should also be declared private.
Danny at 2007-11-11 21:05:20 >
# 8 Re: Singleton
Hello again,

Can you please tell me whether the following is a proper Singelton implementation ? How can I make sure this works, i.e. I'd like to try and call the singelton twice from main(), but want to see a compilation error.

class Ami
{
private:
Ami() {}
Ami(const Ami&);

public:

static Ami& instance()
{
static Ami ami;
return ami;
}

void method()
{
cout << "\tMethod of the singleton class" << endl << endl;
}
~Ami()
{

}
};

int main()
{
Ami::instance().method();

return 0;
}
ami at 2007-11-11 21:06:23 >
# 9 Re: Singleton
You can call instance() as many times as you want. The point is that each call will return the same object, not a different object:

Ami & ref= Ami::instance();
Ami & ref2= Ami::instance();

Here you have two references that are bound to the same object.

However, if you try this:
Ami a; //compilation error
Ami b= Ami::instance(); //compilation error

you will see that you can't create multiple objects of this type.
Danny at 2007-11-11 21:07:25 >
# 10 Re: Singleton
Hi Ami,

it's not the idea of a Singleton to get a compilation error if you attempt to get two
instances, but rather to ensure, that there is only one object (instance) of the
Singleton class.
To make sure you only have one instance, you can for example add a debug message
to the code of your constructor. If the debug message shows more than once. then
you have not a Singleton.
In addition to that you should try to copy construct a Singleton object. This should
fail at compile-time (Constructors should be private!).

Cheers,

D
drkybelk at 2007-11-11 21:08:22 >