#include <cstddef>
class Single {
public:
~Single() {}
static Single* instance() {
if (ptr == NULL) {
ptr = new Single;
}
return ptr;
}
void destory() {
if (ptr != NULL) {
delete ptr;
ptr = NULL;
}
}
int getVal() const {
return i;
}
private:
// constructor
Single() {
i = 0;
}
// copy constructor
Single(Single&);
// assignment constructor
Single& operator = (const Single&);
// members
static Single* ptr;
int i;
};
int main() {
int val = Single::instance()->getVal();
Single::instance()->destory();
mySingle = NULL;
return 0;
}
使用完该单例后,需要释放内存的时候必须注意:
1、不要直接使用类的析构函数来释放,否则将引起无休止的循环!
将析构函数改成如下形式,然后用析构函数来释放
Single::~Single() {
if (ptr != NULL) {
delete ptr;
ptr = NULL;
}
}
Single* mySinglePtr = Single::instance();
delete mySinglePtr;
首先 delete mySinglePtr;会调用Single的析构函数,在析构函数内,进行指针判断,如果不为空,则delete ptr,而ptr所指的对象是Single,则再去调用析构函数,以此往复,形成死循环。
2、正确方法:另提供一个释放的接口,由这个单例的使用者来释放。
示例程序中,提供了destory的接口,用户需要释放内存,则调用改接口。
3、很容易犯的一个错误:(类的定义是示例程序中的,即不调用析构函数,而是用destory来释放内存)
// 用户1
Single* mySinglePtr = Single::instance();
delete mySinglePtr;
mySinglePtr = NULL;
// 用户2在用户1delete后,使用instance
Singel* mySinglePtr2 = Single::instance();
mySinglePtr2->getVal();
// ****此时,出现segment default!!!
原因:用户1delete mySinglePtr后,将Single的实例已经释放掉,但是但是!!Single中的ptr没有复位为空指针!!!!仍然指向之前new出来的内存(但这块内存已经被delete掉,系统已经回收)。用户2要使用instance,Single::instance()判断此时的ptr不为空,就直接返回了ptr指针,ptr指向了已经被系统回收的内存,造成segment default。