C++智能指针循环引用问题

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。
本文链接: https://blog.csdn.net/puliao4167/article/details/89715171

    今天遇到一个问题需要记录一下,C++中的RAII机制对于内存泄漏问题有了很大的帮助。当我们在拿到一块堆空间的时候,就应该用智能指针包裹起来,当对象生命周期结束的时候会自动释放申请的内存。

    智能指针的类型常用的有三种,shared_ptr,unique_ptr,weak_ptr。三种智能指针各有特点,简单而言,shared_ptr有引用计数,unique_ptr一个对象只能指向一块给定内存(不支持拷贝和赋值),weak_ptr是一种“弱”智能指针,不控制对象的生命周期,也不增加引用计数。

    一般都是选择shared_ptr,由于其引用计数功能,每当拷贝一个对象,引用计数就会增加1,同理,当一个shared_ptr对象销毁时候,计数器就会减少1,当计数器为0的时候,shared_ptr就会自动释放其管理的对象。Shared_ptr简单实现。

/*
 * @Description:  share_ptr的实现,注意不能用一个生指针给智能指针初始化(所以构造函数要声明为显式)
 */
#ifndef _SHARE_PTR_H
#define _SHARE_PTR_H
#include <iostream>
#include <string>
template<typename T>
class My_Share_Ptr{
public:
    My_Share_Ptr():a(NULL),num(new int(0)){ }
    explicit My_Share_Ptr(T *ptr):a(ptr),num(new int(1)){ }
    My_Share_Ptr(const My_Share_Ptr& ptr):a(ptr.a),num(ptr.num)
    {
        (*num)++;//引用计数+1
    }
    My_Share_Ptr operator =(const My_Share_Ptr& ptr);
    ~My_Share_Ptr(){
        if(a && (*num)--){
            delete a;
            delete num;
        }
    }
public:
    T& operator*();

    T* operator->();

    inline T* get() const {
        return a;
    }
    inline int user_count() const{
        return *num;
    }
private:
    T *a;//内部指针
    int* num;//引用计数,注意这里一定要指针
};


#endif
#include "share_ptr.h"

template<typename T>
My_Share_Ptr<T> My_Share_Ptr<T>::operator =(const My_Share_Ptr<T>& ptr){
    if(this==&ptr){
        return *this;
    }
    *num--;
    if(*num==0){
        delete num;
        delete a;
    }
    num=ptr.num;
    *num++;
    a=ptr->a;
    return *this;
}

template<typename T>
T& My_Share_Ptr<T>::operator *(){
    if(num==0){
        return (T*) 0;
    }
    return *a;
}

template<typename T>
T* My_Share_Ptr<T>::operator->(){
    if(num==0){
        return 0;
    }
    return a;
}

   接下来进入重点,最近在用shared_ptr的时候发现循环引用的问题,这里需要注意一下。解决的方法就是在类中,用weak_ptr替代shared_ptr。

#include <iostream>
#include <memory>
using namespace std;
class TestA;
class TestB;
class TestA{
public:
    shared_ptr<TestB> ptr1;
public:
    TestA():ptr1(NULL){ }
};

class TestB{
public:
    shared_ptr<TestA> ptr2;
public:
    TestB():ptr2(NULL){ }
};

int main(){
    //以下四句会造成一个互相赋值的僵局(有点类似于死锁,但是不是申请共享资源,而是形成一个链状)
    shared_ptr<TestA> ptrA(new TestA);
    shared_ptr<TestB> ptrB(new TestB);
    ptrA->ptr1=ptrB;
    ptrB->ptr2=ptrA;
    
    return 0;
}

    无论ptrA还是ptrB,都会因为引用计数没有到达0,无法释放在堆上的资源。

猜你喜欢

转载自blog.csdn.net/puliao4167/article/details/89715171
今日推荐