单例模式及其析构

本文深入探讨单例模式在C++中的实现细节,特别是如何避免内存泄漏和死锁问题。通过实例说明了直接调用析构函数可能导致的无限循环,并提出了解决方案——提供专门的销毁接口。同时,强调了在多用户环境中正确释放单例资源的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值