Reputation: 223
I know this is very silly question about singleton pattern but still it is first choice of interviewer. Could you let me know in below code snippet.
(1) After deleting singleton object why still I am able to call show() method and it works fine.
delete obj;
obj=NULL;
obj->show();
(2) After creating obj1 object why i am not able to print the content of acquire_lock and release_lock function even print statment "one Time" will be printed once and if we increment counter i then instead of 2 it is printing 1 only, why?
Foo *obj1=MySingleton<Foo>::GetInstance();
(3) usage of unique_ptr with singleton object will have any negative implications.
code snippet:
#include <iostream>
#include <fstream>
#include <memory>
#include <string>
using namespace std;
static int i;
class Lock
{
public:
Lock(){};
~Lock(){};
void acquire_lock()
{
cout<<"aquired lock for class";
}
void release_lock()
{
cout<<"released lock for class";
}
};
class Foo
{
public:
void show()
{
cout<<"\ndone\n";
}
};
template <class T>
class MySingleton
{
protected:
MySingleton() {}
private:
//holds one and only object of MySingleton
static T* m_pOnlyOneInstance;
MySingleton(const MySingleton <T> &) {};
MySingleton <T> & operator=(const MySingleton <T> &) {};
~MySingleton() {};
public:
static T * GetInstance();
void foo()
{
cout<<"Mohan";
}
};
template <class T>
T* MySingleton<T>::GetInstance()
{
Lock lock;
if (m_pOnlyOneInstance == NULL)
{
lock.acquire_lock();
cout<<"one Time"<<endl;
i++;
if(m_pOnlyOneInstance == NULL)
{
m_pOnlyOneInstance = new T();
}
lock.release_lock();
}
return m_pOnlyOneInstance;
}
template <class T> T* MySingleton<T> :: m_pOnlyOneInstance=NULL;
int main()
{
//std::unique_ptr <Foo> obj (MySingleton<Foo>::GetInstance());
Foo *obj=MySingleton<Foo>::GetInstance();
//obj->show();
delete obj;
obj=NULL;
obj->show();
cout<<"\ncalling again\n";
Foo *obj1=MySingleton<Foo>::GetInstance();
obj1->show();
cout<<"i="<<i;
return 1;
}
Note: lock related function are dummy implementation only.
Upvotes: 5
Views: 108
Reputation: 852
This is not a proper way to delete the singleton object, you need to write below method in order to delete the instance and then execute your programme.
static void cleanup()
{
delete m_pOnlyOneInstance;
m_pOnlyOneInstance= NULL;
}
Here is the output :
aquired lock for classone Time released lock for class done
calling again aquired lock for classone Time released lock for class done i=2
Upvotes: 1
Reputation: 1
Your singleton class should have a private constructor and destructor. The destructor should handle any memory cleanup when the scope of the singleton ends, so there's no need to explicitly delete it. It could be unsafe to delete it when other objects are still accessing the singleton after the point of deletion. You could be getting an undefined behavior when you did "delete obj", and "obj=null" since you overloaded assignment operator and destructor are private.
Upvotes: 0
Reputation: 2156
obj->show()
is equivalent to Foo::show(obj)
. Both expressions set this
to the value of obj
within the show
member function. Now, what would setting this
to NULL
within show
do? Nothing, because you never reference this
.GetInstance
. If an instance does not exist, it instantiates the class (messily... but it does work), and afterwards the instance exists. Otherwise, it does nothing.std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance();
?" As you can see from the reference for unique_ptr
, its purpose is to take ownership of a dynamically allocated resource. This is definitely not supposed to happen when you're dealing with singleton objects. Because the resource (the singleton instance, in this case) is shared among any number of callers, the singleton class is the only one which should be managing the instance resource -- this is a fundamental invariant of the singleton pattern. If you use unique_ptr
, as soon as obj
goes out of scope, it will delete the instance automatically, regardless of whether your program references the now-freed instance elsewhere.Upvotes: 2
Reputation: 22023
(1) The call would fail if it actually used obj either to perform the call or within the call.
First the call it self is to a non virtual function so the obj pointer is not needed to find the function. The compiler already figured out at compile time which function to call.
Second the function does not access any member variables of the class so while it does receive a this pointer that is NULL it actually never uses it.
BTW, it seems that this code tries to use the MySingleton template to turn other classes into singletons but it doesn't really as it doesn't prevent making copies or instantiating objects through other ways so it is no true singleton. The only thing it does is always return the same pointer.
Other BTW, the second call to MySingleton<Foo>::GetInstance()
returns a copy of a pointer that you have previously deleted when you did delete obj
. obj
was set to NULL after the delete but the original pointer in the MySingleton template is still pointing to the deleted object so the second call to GetInstance will happily return the now invalid pointer.
Upvotes: 0