单例模式及其析构

#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。

 

猜你喜欢

转载自blog.csdn.net/chenyingying_/article/details/83029600