C++:线上课程2_19(共享智能指针shared_ptr)


一、智能指针(shared_ptr)

1.观察器

get返回存储的指针
operator*/operator->解引用存储的指针
operator[]提供到被存储数组的带下标访问
use_count返回shared_ptr所指对象的引用计数
unique检查所管理对象是否仅由当前shared_ptr的实例管理
operator bool检查是否有关联的管理对象
owner_before提供基于拥有者的共享指针排序

2.共享指针

共享指针可以同时拥有一块资源。

#ifndef MY_SHARED_PTR_H
#define MY_SHARED_PTR_H
#include<atomic>

template<class _Ty>
class MyDeletor
{
public:
    //MyDeletor() = default;
    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* mptr;
    //int ref;
    std::atomic_int ref;

public:
    RefCnt(_Ty* p = nullptr) :mptr(p), ref(mptr != nullptr) {}
    ~RefCnt() {}
};
template<class _Ty, class _Dx = MyDeletor<_Ty> >
class my_shared_ptr // thread;
{
public:
    my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
    {
        if (p != nullptr)
        {
            ptr = new RefCnt(p);
        }
    }
    my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
    {
        if (ptr != nullptr)
        {
            ptr->ref += 1;
        }
    }// my_shared_ptr<Object> op2(op1);
    my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)//移动构造函数
    {
        _Y.ptr = nullptr;
    }// my_shared_ptr<Object> op2(std::move(op1));
    operator bool() const { return ptr != nullptr; }

    my_shared_ptr& operator=(const my_shared_ptr& _Y)//普通对象赋值语句
    {
        if (this == &_Y || this->ptr == _Y.ptr) return *this;
        if (ptr != NULL && --ptr->ref == 0)
        {
            mDeletor(ptr);
        }
        ptr = _Y.ptr;
        if (ptr != nullptr)
        {
            ptr->ref += 1;
        }
        return *this;
    }
    my_shared_ptr& operator=(my_shared_ptr&& _Y) //移动赋值函数:将资源进行转移,源对象失去资源使用权
    {
        if (this == &_Y) return *this;
        if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
        {
            this->ptr->ref -= 1;
            _Y.ptr = nullptr;
            return *this;
        }
        if (this->ptr != nullptr && --ptr->ref == 0)
        {
            mDeletor(ptr);
        }
        ptr = _Y.ptr;
        _Y.ptr = nullptr;
        return *this;
    }
    void reset(_Ty* p = nullptr)
    {
        if (this->ptr != nullptr && --this->ptr->ref == 0)
        {
            mDeletor(ptr);
        }
        ptr = new RefCnt<_Ty>(p);
    }
    ~my_shared_ptr()
    {
        if (this->ptr != nullptr && --this->ptr->ref == 0)//引用计数为0的时候,说明没有指针指向才可以释放
        {
            mDeletor(ptr->mptr);
            delete ptr;
        }
        ptr = nullptr;
    }
    _Ty* get() const//获得指针
    {
        return ptr->mptr;
    }
    _Ty& operator*() const//重载*
    {
        return *get();
    }
    _Ty* operator->() const//重载->符号
    {
        return get();
    }

    size_t use_count() const//计算有多少对象拥有此资源
    {
        if (this->ptr == nullptr) return 0;
        return this->ptr->ref;
    }
    void swap(my_shared_ptr& r)//交换对象(交换对象指针)
    {
        std::swap(this->ptr, r.ptr);
    }

private:
    RefCnt<_Ty>* ptr;
    _Dx mDeletor;
};

template<class _Ty, class _Dx >
class my_shared_ptr<_Ty[], _Dx>
{
public:
    my_shared_ptr(_Ty* p = nullptr) :ptr(nullptr)
    {
        if (p != nullptr)
        {
            ptr = new RefCnt(p);
        }
    }
    my_shared_ptr(const my_shared_ptr& _Y) :ptr(_Y.ptr)
    {
        if (ptr != nullptr)
        {
            ptr->ref += 1;
        }
    }// my_shared_ptr<Object> op2(op1);
    my_shared_ptr(my_shared_ptr&& _Y) :ptr(_Y.ptr)
    {
        _Y.ptr = nullptr;
    }// my_shared_ptr<Object> op2(std::move(op1));
    operator bool() const { return ptr != nullptr; }

    my_shared_ptr& operator=(const my_shared_ptr& _Y) // 
    {
        if (this == &_Y || this->ptr == _Y.ptr) return *this;
        if (ptr != NULL && --ptr->ref == 0)
        {
            mDeletor(ptr->mptr);
            delete ptr;
        }
        ptr = _Y.ptr;
        if (ptr != nullptr)
        {
            ptr->ref += 1;
        }
        return *this;
    }
    my_shared_ptr& operator=(my_shared_ptr&& _Y) // move operator =
    {
        if (this == &_Y) return *this;
        if (this->ptr == _Y.ptr && this->ptr != nullptr && _Y.ptr != nullptr)
        {
            this->ptr->ref -= 1;
            _Y.ptr = nullptr;
            return *this;
        }
        if (this->ptr != nullptr && --ptr->ref == 0)
        {
            mDeletor(ptr->mptr);
            delete ptr;
        }
        ptr = _Y.ptr;
        _Y.ptr = nullptr;
        return *this;
    }
    void reset(_Ty* p = nullptr)
    {
        if (this->ptr != nullptr && --this->ptr->ref == 0)
        {
            mDeletor(ptr->mptr);
            delete ptr;
        }
        ptr = new RefCnt<_Ty>(p);
    }
    ~my_shared_ptr()
    {
        if (this->ptr != nullptr && --this->ptr->ref == 0)
        {
            mDeletor(ptr->mptr);
            delete ptr;
        }
        ptr = nullptr;
    }
    _Ty* get() const { return ptr->mptr; }
    _Ty& operator*() const
    {
        return *get();
    }
    _Ty* operator->() const
    {
        return get();
    }

    size_t use_count() const
    {
        if (this->ptr == nullptr) return 0;
        return this->ptr->ref;
    }
    void swap(my_shared_ptr& r)
    {
        std::swap(this->ptr, r.ptr);
    }

    _Ty& operator[](const int idx) const
    {
        return ptr->mptr[idx];
    }

private:
    RefCnt<_Ty>* ptr;
    _Dx mDeletor;
};
#endif

3.相互引用

导致对象无法释放,所以编译错误

#include<iostream>
using namespace std;

class Child;
class Parent
{
	shared_ptr<Child> child;
	Parent()
	{
		cout << "Parent" << endl;
	}
	~Parent()
	{
		cout << "~Parent" << endl;
	}
	void hi()
	{
		cout << "hello" << endl;
	}
};
class Child
{
public:
	shared_ptr<Parent> parent;
	Child()
	{
		cout << "Child" << endl;
	}
	~Child()
	{
		cout << "~Child" << endl;
	}
};
void fun()
{
	shared_ptr<Parent> p = make_shared<Parent>();
	shared_ptr<Parent> c = make_shared<Child>();

	p->child = c;
	p->parent = p;
	c->parent->hi();
}

在这里插入图片描述


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值