use*_*354 5 c++ templates design-patterns smart-pointers
我知道这是关于单身人士模式的非常愚蠢的问题,但它仍然是面试官的首选.你可以在下面的代码片段中告诉我吗?
(1)删除单例对象后,为什么我仍然可以调用show()方法,它工作正常.
delete obj;
obj=NULL;
obj->show();
Run Code Online (Sandbox Code Playgroud)
(2)创建obj1对象后,为什么我无法打印acquire_lock和release_lock函数的内容,即使打印状态"一次"也会打印一次,如果我们增加计数器i而不是2则只打印1,为什么?
Foo *obj1=MySingleton<Foo>::GetInstance();
Run Code Online (Sandbox Code Playgroud)
(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;
}
Run Code Online (Sandbox Code Playgroud)
注意:锁相关功能仅为虚拟实现.
(1) 如果实际使用 obj 来执行调用或在调用内,则调用将失败。
首先,调用 self 是对非虚函数的调用,因此不需要 obj 指针来查找该函数。编译器在编译时就已经确定要调用哪个函数。
其次,该函数不访问类的任何成员变量,因此虽然它确实收到了 NULL 的 this 指针,但它实际上从不使用它。
顺便说一句,这段代码似乎试图使用 MySingleton 模板将其他类转换为单例,但事实并非如此,因为它不会阻止通过其他方式复制或实例化对象,因此它不是真正的单例。它唯一做的就是始终返回相同的指针。
顺便说一句,第二次调用会MySingleton<Foo>::GetInstance()返回您之前删除的指针的副本delete obj。obj删除后设置为 NULL,但 MySingleton 模板中的原始指针仍然指向已删除的对象,因此第二次调用 GetInstance 将很高兴地返回现在无效的指针。