Query related to single element behavior

I know this is a very stupid question about a singleton circuit, but still this is the interviewer's first choice. Could you tell me the code snippet below.

(1) After deleting the singleton object, why can I still call the show () method and it works fine.

delete obj; obj=NULL; obj->show(); 

(2) After creating the obj1 object, why can't I print the contents of the gets_lock and release_lock functions, even the printed β€œone time” application will be printed once, and if we increase counter i, and instead of 2, it will print only 1, why?

 Foo *obj1=MySingleton<Foo>::GetInstance(); 

(3) using unique_ptr with a singleton object will have any negative consequences.

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. A lock-related function is only a dummy implementation.

+5
source share
4 answers
  • Keep in mind that obj->show() equivalent to Foo::show(obj) . Both expressions set this to obj inside the show member function. Now, what would make setting this to NULL inside show ? Nothing, because you never reference this .
  • Well, think about the whole reason you should use the singleton pattern - to initialize something no more than once. This print statement "once" is in the code where the instance of the object is created, so naturally it does not start after the first time. Look at the logic of GetInstance . If the instance does not exist, it creates an instance of the class (randomly ... but it works), and then the instance exists. Otherwise, he does nothing.
  • This question is very unclear, but I assume that you mean "what are the negative consequences of doing std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance(); ;?" As you can see from the reference for unique_ptr , its purpose is to take responsibility for a dynamically allocated resource. This definitely should not happen when you are dealing with singleton objects. Since the resource (a singleton instance, in this case) is distributed between any number of callers, the singleton class is the only one that must manage the instance resource - this is the fundamental invariant of the singleton template. If you use unique_ptr as soon as obj goes out of scope, it will automatically delete the instance, regardless of whether your program refers to the instance that is currently freed up elsewhere.
+2
source

This is not the correct way to delete a singleton object, you need to write a method below to delete an instance and then execute your program.

 static void cleanup() { delete m_pOnlyOneInstance; m_pOnlyOneInstance= NULL; } 

Here is the result:

lock for classic time freed lock for class done

call again lock for class vacated lock for class done = 2

+1
source

(1) The call failed if he actually used obj to make the call or inside the call.

At first, the call itself refers 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.

Secondly, the function does not have access to any member variables of the class, so when it gets this pointer, which is NULL, it never actually uses it.

By the way, this code is trying to use the MySingleton template to turn other classes into single ones, but in reality it is not like this does not interfere with creating copies or creating objects in other ways, so this is not a true singleton. The only thing it does is always return the same pointer.

Another BTW, the second call to MySingleton<Foo>::GetInstance() returns a copy of the pointer that you previously deleted when you did delete obj . obj was set to NULL after deletion, but the original pointer in the MySingleton template still points to the remote object, so the second GetInstance call will happily return an invalid pointer.

0
source

Your singleton class must have a private constructor and destructor. The destructor must handle any memory flushing when the Singleton scope expires, so there is no need to explicitly delete it. This may not be safe to delete when other objects still access the singleton after the delete point. You can get undefined behavior when you "delete obj" and "obj = null" because you are overloaded with the assignment operator and the destructor is private.

0
source

All Articles