im making a singleton class in c++ and have a couple of questions. first, heres my .h and .cpp files:

// Singleton.h

class Singleton
{
public:
	static Singleton GetSingleton();
	void DoSomething();
	~Singleton();

private:
	Singleton();		
	static Singleton* _instance;
};
//Singleton.cpp

Singleton* Singleton::_instance = 0;// initialize pointer
//*********************************************************************************************
Singleton::Singleton()
{	
	std::cout << "Singleton::Singleton" << std::endl;
}

//*********************************************************************************************
Singleton::~Singleton()
{
	std::cout << "Singleton::~Singleton" << std::endl;
}

//*********************************************************************************************
Singleton Singleton::GetSingleton()
{
	std::cout << "Singleton::GetSingleton" << std::endl;
	if(_instance == NULL)
	{
		_instance = new Singleton();
	}
	return *_instance;
}

//*********************************************************************************************
void Singleton::DoSomething()
{
	std::cout << "Singleton::DoSomething" << std::endl;
}

then in my main.cpp, i simply call:

int _tmain(int argc, _TCHAR* argv[])
{
	Singleton::GetSingleton().DoSomething();

	return 0;
}

The output is:

Singleton:: GetSingleton
Singleton:: Singleton
Singleton:: DoSomething
Singleton:: ~Singleton


Question 1 - why does the constructor get called ? i never call delete. i would expect the constructor to get called because of the 'new' in ::GetSingleton, but not the destructor.

Question 2 - if i make the destrcutor private, why does the compiler say

Error 2 error C2248: 'Singleton::~Singleton' : cannot access private member declared in class 'Singleton' d:\myWork\paulstest1\main.cpp 12 PaulsTest1

when i am blatently not accessing the destructor anywhere.

thanks in advance.

You have a very non-obvious error: the default copy constructor is in use.

Make sure that GetSingleton() returns a pointer to type Singleton.

Hope this helps.

yes, that indeed fixes the problem, thank you.

however, i would still like to understand why that was happening. at what point does the default copy constructor get called in my sample code above, and why does the default copy constructor result in the destructor being called ?

[edit]
ok, so i added a copy constructor (that just output cout << "Singleton:: Singleton[ctr]") and then i called DoSomething twice, and this was the output:

Singleton:: GetSingleton
Singleton:: Singleton
Singleton:: Singleton[ctr]
Singleton:: DoSomething
Singleton:: ~Singleton
Singleton:: GetSingleton
Singleton:: Singleton[ctr]
Singleton:: DoSomething
Singleton:: ~Singleton

so the actual main constructor get called once, which is what i would expect when we called 'new' in GetSingleton just the one and only time. then further calls to GetSingleton invoke the copy constructor seem to create a copy of the singleton via the copy constructor, then this copy gets destroyed and the end of GetSingleton.

so now i can see 'what' is happening, i am still unsure as to 'when' this is happening. ie at what point exactly does the copy constructor get called ?
[/edit]

thanks again.

Hi Buddy,
I've gone through the issue you mentioned.
it's very simple to find and to say its not a problem but the way it works.

if you look at your main and see what function you are calling it will be clear to you.
In main you did
(1) Singleton::GetSingleton().DoSomething();
So first the control will goto GetSingleton, as the instance pointer is null it will invoke the constructor and construct the object then after it will call DoSomething as asked to do
Now when the main will end the destructor will be invoked by default and it will do clean-up

Singleton Singleton::GetSingleton()
{
	std::cout << "Singleton::GetSingleton" << std::endl;
	if(_instance == NULL)
	{
		_instance = new Singleton();
	}
	return *_instance;
}
Singleton Singleton::GetSingleton()

GetSingleton() returns an object, not a reference or pointer, so

return *_instance;

returns a copy of what _instance points to.

This article has been dead for over six months. Start a new discussion instead.