I asked a question about singleton implementation a few minutes ago, I've got very good answer from @LightnessRacesinOrbit.
But I cannot understand why in the next example if I instantiate Singleton
in variable inst
its destructor called twice?
#include <iostream>
class Singleton
{
public:
~Singleton() { std::cout << "destruction!\n"; }
static Singleton& getInstance()
{
static Singleton instance;
return instance;
}
void foo() { std::cout << "foo!\n"; }
private:
Singleton() { std::cout << "construction!\n"; }
};
int main()
{
Singleton inst = Singleton::getInstance();
inst.foo();
}
Output:
construction!
foo!
destruction!
destruction!
Live demo
To be more correct, I understand why it is called twice. But I cannot understand how it can be called twice if after first destructor the instance of the class was destroyed? Why there is no exception?
Or it was not destroyed? Why?
C++ destructors are called twice for local objects when exiting a function via a nested return statement.
The Singleton's purpose is to control object creation, limiting the number to one but allowing the flexibility to create more objects if the situation changes. Since there is only one Singleton instance, any instance fields of a Singleton will occur only once per class, just like static fields.
Because all the member functions of this class are static and the class has no instance variables, it is not required that the class be instantiated. The member functions can be used without an instance of the class. Thus there is no need to implement constructors or a destructor for this class.
There is no way to destroy a Singleton without breaking the Singleton property. As others have said, maybe a Singleton isn't appropriate here. If the number of instances of the class can go down to zero, then it's not a Singleton.
This line
Singleton inst = Singleton::getInstance();
Should be
Singleton& inst = Singleton::getInstance();
Then you would only see one destructor call.
The way it is written, Singleton::getInstance()
returns a reference, but then copies it to inst
. So both the Singleton
returned from your function and the copy are destroyed. You never saw the copy get constructed because the default constructor was not used, the copy constructor was.
In the second method, the reference is returned, then you just have inst
be a reference to that Singleton
instead of making a copy.
As other's have mentioned, you can make the class non-copyable and non-movable to prevent this
Singleton(Singleton const&) = delete; // Copy construct
Singleton(Singleton&&) = delete; // Move construct
Singleton& operator=(Singleton const&) = delete; // Copy assign
Singleton& operator=(Singleton &&) = delete; // Move assign
The line
Singleton inst = Singleton::getInstance();
copies your instance with the auto-generated copy-constructor. To prevent this from happening, add
Singleton( const Singleton& ) = delete;
to your class to prevent those accidential copies. To make sure that even more obscure mistakes are caught, also add
void operator=( const Singleton& ) = delete;
as well. You don't have to explicitly delete move construction or assignment as the compiler will not generate them with the other (deleted) members declared.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With