欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

智能指针——shared_ptr & weak_ptr

程序员文章站 2022-06-02 13:56:03
...

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

循环引用
由于引用计数和管理空间的对象的个数导致空间不能释放的结果就是循环引用。
智能指针——shared_ptr & weak_ptr
下面是对于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;
}