智能指针——shared_ptr & weak_ptr

shared_ptr(引用计数) & weak_ptr
让auto_ptr和scoped_ptr 很费脑子的一件事情就是:在拷贝构造和赋值操作的时候,进行的是浅拷贝,就会在析构的时候对同一块空间析构多次。
对于此问题,有一个很经典的解决办法:引用计数!!!
在拷贝构造和赋值运算符重载的时候,原指针 ap1 和 ap2 共享一个引用计数,对该引用计数进行++
在析构的时候,查看引用计数是否为1,若为1,表示只有当前指针使用这块空间,可以对该指针进行释放清理;
若大于1,表示还有其它指针在使用这块空间,只需要将引用计数进行 - -,不需要释放这块空间。

循环引用
由于引用计数和管理空间的对象的个数导致空间不能释放的结果就是循环引用。
循环引用
下面是对于shared_ptr和weak_ptr的简单实现:

#include <iostream>
using namespace std;

template <class T>
class weak_ptr;

template <class T>
class shared_ptr
{
    friend class weak_ptr<T>;

public:
    shared_ptr(T* ptr)
        :_ptr(ptr)
        ,_refcount(new int(1))
    {
        cout<<"shared_ptr()"<<endl;
    }

    shared_ptr(const shared_ptr<T>& sp)
        :_ptr(sp._ptr)
        ,_refcount(sp._refcount)
    {
        (*_refcount)++;
    }

    shared_ptr<T>& operator=(const shared_ptr<T>& sp)
    {
        if(_ptr != sp._ptr)
        {
            if(--(*_refcount) == 0)         // 判断该指针的这块空间是否只有它自己在使用,
            {
                delete _ptr;                // 如果是,则清理这块空间(因为在调用赋值之后,该指针与sp共享一块空间,这块空间就没用了)
                delete _refcount;
            }

            _ptr = sp._ptr;                // 如果不是,直接赋值(浅拷贝)
            _refcount = sp._refcount;
            (*_refcount)++;
        }
        return *this;
    }

    T& operator*()
    {
        return *_ptr;
    }

    T* operator->()
    {
        return _ptr;
    }

    int get_count()
    {
        return *_refcount;
    }

    ~shared_ptr()
    {
        if(--(*_refcount)  == 0)
        {
            delete _ptr;
            delete _refcount;
        }
        cout<<"~shared_ptr()"<<endl;
    }

private:
    T* _ptr;
    int* _refcount;
};

/
// shared_ptr 可能会有循环引用的问题
// 在可能出现循环引用的情况下,需要与weak_ptr搭配使用
template <class T>
class weak_ptr
{
public:
    weak_ptr(const shared_ptr<T>& sp)
        :_ptr(sp._ptr)
    {}

    T& operator*()
    {
        return *_ptr;
    }

    T* operator->()
    {
        return _ptr;
    }

private:
    T* _ptr;
};

struct ListNode
{
    int _data;
    weak_ptr<ListNode> _next;
    weak_ptr<ListNode> _prev;
    
    ListNode()
	    :_next(NULL)
	    ,_prev(NULL)
    {}
    
    // ~ListNode()
    // {
    //     cout<<"~ListNode()"<<endl;
    // }
};


int main()
{
    
    // shared_ptr

    // shared_ptr<int> sp1(new int(1));
    // *sp1 = 10;
    // cout<<"count:"<<sp1.get_count()<<endl;
    // // cout<<*sp1<<endl;
    //
    // shared_ptr<int> sp2(sp1);
    // cout<<"count:"<<sp1.get_count()<<endl;
    // shared_ptr<int> sp3(new int(1));

    // // cout<<*sp3<<endl;
    // sp3 = sp1;
    // // cout<<*sp3<<endl;
    // cout<<"count:"<<sp1.get_count()<<endl;
   

    
    // weak_ptr

    // weak_ptr<int> wp1(new int(1));
    shared_ptr<ListNode> l1(new ListNode);
    shared_ptr<ListNode> l2(new ListNode);
    cout<<l1.get_count()<<endl;
    cout<<l2.get_count()<<endl;

    l1->_next = l2;
    l2->_prev = l1;
    cout<<l1.get_count()<<endl;
    cout<<l2.get_count()<<endl;
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值