C++ 单例行为相关查询
我知道这是一个关于单身模式的愚蠢问题,但它仍然是面试官的首选。 你能告诉我下面的代码片段吗 (1) 删除singleton对象后,为什么我仍然能够调用show()方法,并且它工作正常C++ 单例行为相关查询,c++,templates,design-patterns,smart-pointers,C++,Templates,Design Patterns,Smart Pointers,我知道这是一个关于单身模式的愚蠢问题,但它仍然是面试官的首选。 你能告诉我下面的代码片段吗 (1) 删除singleton对象后,为什么我仍然能够调用show()方法,并且它工作正常 delete obj; obj=NULL; obj->show(); (2) 创建obj1对象后,为什么我无法打印获取锁定和释放锁定功能的内容?即使打印状态“一次”也会打印一次,如果我们增加计数器i,而不是2,它只打印1,为什么 Foo *obj1=MySingleton<Foo>::GetIn
delete obj;
obj=NULL;
obj->show();
(2) 创建obj1对象后,为什么我无法打印获取锁定和释放锁定功能的内容?即使打印状态“一次”也会打印一次,如果我们增加计数器i,而不是2,它只打印1,为什么
Foo *obj1=MySingleton<Foo>::GetInstance();
Foo*obj1=MySingleton::GetInstance();
(3) 将unique_ptr与singleton对象一起使用会产生任何负面影响
代码段:
#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;
}
#包括
#包括
#包括
#包括
使用名称空间std;
静态int-i;
类锁
{
公众:
锁(){};
~Lock(){};
无效获取_锁()
{
cout(1)
如果调用实际使用obj执行调用或在调用中使用obj,则调用将失败
首先,调用它本身是一个非虚函数,因此不需要obj指针来查找该函数。编译器在编译时已经确定了要调用哪个函数
第二,函数不访问类的任何成员变量,因此当它确实接收到一个this指针为NULL时,它实际上从不使用它
顺便说一句,这段代码似乎试图使用MySingleton模板将其他类转换为单例,但实际上并没有,因为它不阻止通过其他方式复制或实例化对象,所以它不是真正的单例。它所做的唯一事情就是始终返回相同的指针
顺便说一句,第二个调用是MySingleton::GetInstance()
返回以前在执行delete obj
时删除的指针的副本obj
在删除后被设置为NULL,但MySingleton模板中的原始指针仍指向删除的对象,因此对GetInstance的第二次调用将愉快地返回现在无效的指针
请记住,obj->show()
相当于Foo::show(obj)
。这两个表达式都在show
成员函数中将this
设置为obj
的值。现在,在show
中将this
设置为NULL
将做什么?什么都不做,因为您从未引用this
好吧,首先考虑一下使用singleton模式的全部原因——最多一次初始化一个东西,“一次”print语句位于实例化对象的代码中,因此在第一次之后自然不会执行它。请查看GetInstance
的逻辑。如果实例不存在,它将实例化类(混乱地…但它确实起作用),然后实例就存在了。否则,它什么也不做
这个问题很不清楚,但我想你的意思是“做std::unique\u ptr obj=MySingleton::GetInstance();
,有什么负面影响?”正如您从forunique\u ptr
中所看到的,它的目的是获得动态分配资源的所有权。在处理单例对象时,这绝对不应该发生。因为资源(在本例中为单例实例)在任何数量的调用方之间共享,singleton类是唯一应该管理实例资源的类——这是singleton模式的基本不变形式。如果使用unique\u ptr
,只要obj
超出范围,它就会自动删除实例,而不管您的程序是否引用将现在已释放的实例复制到其他位置
您的singleton类应该有一个私有构造函数和析构函数。当singleton的作用域结束时,析构函数应该处理任何内存清理,因此不需要显式删除它。当其他对象在删除点之后仍在访问singleton时,删除它可能是不安全的。您可能会得到一个未定义的由于重载赋值运算符和析构函数是私有的,因此当您执行“delete obj”和“obj=null”操作时会导致异常行为。这不是删除singleton对象的正确方法,您需要编写下面的方法来删除实例,然后执行程序
static void cleanup()
{
delete m_pOnlyOneInstance;
m_pOnlyOneInstance= NULL;
}
以下是输出:
获得一次锁
释放类的锁
完成
再次呼叫
获得一次锁
释放类的锁
完成
i=2我同意我们需要在singleton类中清理静态方法来删除对象,但正如我在问题中澄清的那样,这纯粹是访谈问题。感谢澄清。对于第(1)点,如果我不设置NULL,它仍然有效,对于第(2)点如果我们删除singleton对象,那么我是否需要通过实现用于删除singleton对象的静态清理方法来设置m_pOnlyOneInstance=NULL。(1)是的,该成员函数从不引用此
,因此使用什么值自然无关紧要。(2)是的,否则您的GetInstance
函数将不知道是否需要稍后再次实例化该类。但是只有当您确定没有其他变量引用该单例时,才可以使用静态清理函数,因此我不推荐使用它。您的意思是说,我们不需要为在应用程序退出时显式删除singleton对象。感谢它进行了适当的清理,现在我得到了适当的输出。