我知道这是关于单身人士模式的非常愚蠢的问题,但它仍然是面试官的首选。 你可以在下面的代码片段中告诉我。
(1)删除单例对象后,为什么我仍然可以调用show()方法,它工作正常。
delete obj;
obj=NULL;
obj->show();
(2)创建obj1对象之后,为什么我无法打印acquire_lock和release_lock函数的内容,即使打印语句“一次”也会打印一次,如果我们增加计数器i而不是2,则只打印1 ,为什么?
Foo *obj1=MySingleton<Foo>::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;
}
注意:锁相关函数只是虚拟实现。
答案 0 :(得分:2)
obj->show()
相当于Foo::show(obj)
。这两个表达式都将this
设置为obj
成员函数中show
的值。现在,this
中NULL
到show
的设置是什么?没什么,因为你从不引用this
。GetInstance
的逻辑。如果一个实例不存在,它会实例化该类(乱七八糟......但确实有效),之后实例就存在了。否则,它什么都不做。std::unique_ptr<Foo> obj = MySingleton<Foo>::GetInstance();
的负面影响是什么?&#34;正如您在unique_ptr
unique_ptr
中所看到的,其目的是获取动态分配资源的所有权。当你处理单例对象时,这肯定是不。因为资源(在这种情况下是单例实例)在任意数量的调用者之间共享,所以单例类是唯一应该管理实例资源的类 - 这是单例模式的基本不变量。如果您使用obj
,只要{{1}}超出范围,它就会自动删除实例,无论您的程序是否在其他地方引用了现已释放的实例。答案 1 :(得分:1)
这不是删除单例对象的正确方法,您需要编写以下方法以删除实例然后执行您的程序。
Thread.sleep(8000);
这是输出:
为classone Time获取锁定 释放锁定课程 完成
再次打电话 获得了锁定时间的锁定 释放锁定课程 DONE I = 2答案 2 :(得分:0)
(1) 如果它实际上使用obj来执行呼叫或在呼叫中,则呼叫将失败。
首先,它自己调用非虚函数,因此不需要obj指针来查找函数。编译器已经在编译时计算出要调用的函数。
其次,该函数不访问该类的任何成员变量,因此当它确实收到一个NULL指针时,它实际上从不使用它。
顺便说一句,似乎这段代码试图使用MySingleton模板将其他类转换为单例,但它并不是真的,因为它不会阻止通过其他方式复制或实例化对象,所以它不是真正的单身人士。它唯一能做的就是返回相同的指针。其他BTW,对D:\android-sdk\platform-tools>adb remount
remount succeeded
D:\android-sdk\platform-tools>adb shell
root@generic_x86_64:/ # adb install 1.apk
adb install 1.apk
Invalid APK file: 1.apk
255|root@generic_x86_64:/ # adb push 1.apk /sdcard
adb push 1.apk /sdcard
error: device offline
1|root@generic_x86_64:/ #
1|root@generic_x86_64:/ # ls
ls
acct
cache
charger
config
d
data
的第二次调用会返回您在执行MySingleton<Foo>::GetInstance()
时先前删除的指针的副本。删除后delete obj
设置为NULL,但MySingleton模板中的原始指针仍然指向已删除的对象,因此第二次调用GetInstance将很高兴地返回现在无效的指针。
答案 3 :(得分:0)
你的单例类应该有一个私有的构造函数和析构函数。当单例的范围结束时,析构函数应该处理任何内存清理,因此不需要显式删除它。当其他对象在删除点之后仍然访问单例时,删除它可能是不安全的。当你执行“删除obj”和“obj = null”时,你可能会得到一个未定义的行为,因为你重载了赋值运算符和析构函数是私有的。