weak_ptr智能指针

本文详细介绍了智能指针`shared_ptr`和`weak_ptr`的工作原理,以及它们如何解决C++中的循环引用问题。通过自定义的`my_shared_ptr`和`my_weak_ptr`实现,展示了引用计数的管理,并阐述了`weak_ptr`的`lock()`函数在检查对象存活状态中的作用。此外,通过一个示例展示了`weak_ptr`如何防止对象的循环引用导致的销毁顺序问题。
摘要由CSDN通过智能技术生成

目录

1.weak_ptr

2.源码

3.注意:  

4.用weak_ptr克服循环引用

对象销毁顺序

 //基础的构建weak_ptr在内存中的


1.weak_ptr

weak_ptr是为了配合shared_ptr而引入的智能指针,它指向一个由shared_ptr管理的对象而不影响所指对象的生命周期;不论是否有weak_ptr的指向,一个指向对象的shared_ptr被销毁,对象就会释放。更像是shared_ptr的助手,但weak_ptr拥有一套不纳入计数器的指针系统

2.源码

//weak_ptr
//弱引用--父子关系的问题
//--弱引用克服循环引用,
template<class _Ty>
class MyDeletor
{
public:
    MyDeletor() {}
    void operator()(_Ty* ptr) const
    {
        if (ptr != nullptr)
            delete ptr;
    }
};

template<class _Ty>
class MyDeletor<_Ty[]>
{
public:
    MyDeletor() = default;//明确的告知有构造函数
    void operator()(_Ty* ptr) const
    {
        if (ptr != nullptr)
            delete[] ptr;
    }
};


template<class _Ty>
class RefCnt
{
public:
    _Ty* _Ptr;
    std::atomic_int _Uses;
    std::atomic_int _Weaks;
public:
    RefCnt(_Ty* p):_Ptr(p),_Uses(1),_Weaks(1){}
    ~RefCnt(){}
    void _Incref() { _Uses += 1; }//shared_ptr引用计数
    void _Incwref() { _Weaks += 1; }//weak_ptr引用计数
};
template<class _Ty>
class my_weak_ptr;

template <class _Ty,class _Dx=MyDeletor<_Ty>>
class my_shared_ptr
{
private:
    _Ty* _Ptr;
    RefCnt<_Ty>* _Rep;
    _Dx _mDeletor;
public:
    my_shared_ptr(_Ty* p = nullptr) :_Ptr(nullptr), _Rep(nullptr)
    {
        if (p != NULL)
        {
            _Ptr = p;
            _Rep = new RefCnt<_Ty>(p);
        }
    }
    //拷贝构造--构造一个对象
    my_shared_ptr(const my_shared_ptr& _Y):_Ptr(_Y._Ptr),_Rep(_Y._Ptr)
    {
        if (_Rep != nullptr) 
        {
            _Rep->_Incref();
        }
    }
    //移动构造
    //my_shared_ptr(my_shared_ptr&& other):_Ptr(nullptr),_Rep(nullptr)
    //{swap(*this,other._Ptr);}
    my_shared_ptr(my_shared_ptr&& other) :_Ptr(other._Ptr), _Rep(other._Rep)
    {
        other._Ptr = nullptr;
        other._Rep = nullptr;
    }
    ~my_shared_ptr()
    {
        if (_Rep != nullptr && --_Rep->_Uses == 0)
        {
            _mDeletor(_Ptr);
            if (_Rep->_Weaks == 0)
            {
                delete _Rep;
            }
        }
        _Ptr = nullptr;
        _Rep = nullptr;

    }
    my_shared_ptr& operator=(const my_shared_ptr& r)
    {
        if (this == r || this->_Ptr == r._Ptr)    return *this;
        if (_Ptr != nullptr && --_Rep->_Uses == 0)
        {
            _mDeletor(_Ptr);
            if (--_Rep->_Weaks == 0)
            {
                delete _Rep;
            }
        }
        _Ptr = r._Ptr;
        _Rep = r._Rep;
        if (_Ptr != nullptr)
        {
            _Rep->_Incref();
        }
        return *this;
    }

    my_shared_ptr& operator=(const my_shared_ptr&& other)
    {
        if (this == &other)return*this;
        if (_Ptr != nullptr && other._Ptr != nullptr && _Ptr == other->_Ptr)
        {
            this->_Rep->_Uses -= 1;
            other._Ptr = nullptr;
            other._Rep = nullptr;
            return*this;
        }
        if (_Ptr != nullptr && --_Rep->_Uses == 0) 
        {
            _mDeletor(_Ptr);
            if (--_Rep->_Weaks == 0) {
                delete _Rep;
            }
        }
        _Ptr = other._Ptr;
        _Rep = other._Rep;
        _Ptr = nullptr;
        _Rep = nullptr;
        return *this;
    }
    //获取对象的指针
    //*
    _Ty* get()const { return _Ptr; }
    //返回对象自身
    _Ty& operator*()const { return *get(); }
    _Ty* operator->()const { return get(); }
    size_t use_count()const
    {
        if (_Rep == nullptr)    return 0;
        return _Rep->_Uses;
    }
    void swap(my_shared_ptr&& r)
    {
        std::swap(_Ptr, r._Ptr);
        std::swap(_Ptr, r.Ptr);
    }
    //是否持有对象
    operator bool()const { return _Ptr != nullptr; }

    template<class _Ty>
    friend class my_weak_ptr;
};
template<class _Ty>
class my_weak_ptr
{
private:
    RefCnt<_Ty>* _Rep; 
public:
    my_weak_ptr() :_Rep(nullptr) {}
    my_weak_ptr(const my_shared_ptr<_Ty>& other) :_Rep(other._Rep)
    {
        if (_Rep != nullptr)
        {
            _Rep->_Incwref();
        }
    }
    //弱引用计数只加弱引用计数的个数,强引用也一样
    //析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
    //弱引用计数只能析构计数结构,不能析构对象
    my_weak_ptr(const my_weak_ptr& other) :_Rep(other._Rep)
    {
        if (_Rep != nullptr)
        {
            _Rep->_Incwref();
        }
    }
    my_weak_ptr(my_weak_ptr&& other) :_Rep(other._Rep)
    {
        other._Rep = nullptr;
    }

    my_weak_ptr& operator=(const my_weak_ptr& other)
    {
        if (this == &other || this->_Rep == other)    return *this;
        if (_Rep != nullptr && --_Rep->_Weaks == 0)
        {
            delete _Rep;
        }
        _Rep = other->_Rep;
        if (_Rep != nullptr)
        {
            _Rep->_Incwref();
        }
        return *this;
    }
    my_weak_ptr& operator=(my_weak_ptr&& other)
    {
        if (this == &other)    return *this;
        if (this->_Rep != nullptr && other._Rep != nullptr && _Rep == other._Rep)
        {
            this->_Rep ->_Weaks -= 1;
            other._Rep = nullptr;
            return *this;
        }
        if (_Rep != nullptr && --_Rep->_Weaks == 0)
        {
            delete _Rep;
        }
        _Rep = other._Rep;
        other._Rep = nullptr;
        return *this;
    }

    my_weak_ptr& operator=(const my_shared_ptr<_Ty>& other)
    {
        if (_Rep != nullptr && --_Rep->_Weaks == 0)
        {
            delete _Rep;
        }
        _Rep = other._Rep;
        if (_Rep != nullptr)
        {
            _Rep->_Incwref();
        }
        return *this;
    }
    //不能进行移动赋值
    // 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
    // 弱引用检测RefCnt结构是否存在,解决环形引用
    my_weak_ptr& operator=(my_shared_ptr<_Ty>&& other) = delete;

    ~my_weak_ptr()
    {
        if (_Rep != nullptr && --_Rep->_Weaks == 0)
        {
            delete _Rep;
        }
        _Rep = nullptr;
    }
    //检测被引用的对象是否被删除//true删除
    bool expired()const
    {
        return this->_Rep->_Uses==0;
    }
    //弱引用没有重载指向符
    //锁住弱引用锁住的对象
    //构建临时对象,指针全都给该对象
    my_shared_ptr<_Ty> lock()const
    {
        my_shared_ptr<_Ty> _Ret;
        _Ret._Ptr = _Rep->_Ptr;
        _Ret._Rep = _Rep;
        _Ret._Rep->_Incref();
        return _Ret;
    }
};

3.注意:  

 //弱引用计数只加弱引用计数的个数,强引用也一样
    //析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
    //弱引用计数只能析构计数结构,不能析构对象

//不能进行移动赋值
    // 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
    // 弱引用检测RefCnt结构是否存在,解决环形引用

如何判断weak_ptr指向的对象是否还存在---lock()函数实现

 //弱引用计数只加弱引用计数的个数,强引用也一样
    //析构的时候强引用计数要析构强引用计数个数,也析构弱引用计数个数
    //弱引用计数只能析构计数结构,不能析构对象

//不能进行移动赋值
    // 原因:移动赋值要把资源赋值给弱指针,但弱智者不拥有资源,
    // 弱引用检测RefCnt结构是否存在,解决环形引用

如何判断weak_ptr指向的对象是否还存在---lock()函数实现

4.用weak_ptr克服循环引用

class Object
{
private:
    int value;
public:
    Object(int x = 0) :value(x) { cout << "Object" << endl; }
    ~Object() { cout << "~Object" << endl; }
};

//--弱引用克服循环引用,对象销毁的顺序?

class Child;
class Parent
{
public: 
    my_weak_ptr<Child> c;
public:
    Parent() { cout << "Parent" << endl; }
    ~Parent() { cout << "~Parent" << endl; }
    void hi()const { cout << "hello parent" << endl; }
};
class Child
{
public:
    my_weak_ptr<Parent> p;
    Child() { cout << "Child" << endl; }
    ~Child() { cout << "Child" << endl; }
};
void fun()
{
    my_shared_ptr<Parent> parent(new Parent());
    my_shared_ptr<Child> child(new Child());
    parent->c = child;
    child->p = parent;
    child->p.lock()->hi();
}

对象销毁顺序

 //基础的构建weak_ptr在内存中的

void fun()
{

    my_shared_ptr<Object> op1(new Object(10));
    my_weak_ptr<Object> wp1(op1);
    my_weak_ptr<Object> wp2(op1);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值