C++智能指针shared_ptr的简单实现

#include <iostream>
#include <memory>
#include <set>
using namespace std;
class Stu//测试类
{
private:
    string name;
    int age;
public:
    Stu(string name, int age)
    {
        this->name = name;
        this->age = age;
        cout << "Stu的构造" << endl;
    }
    Stu(const Stu& stud){
        cout<<"copy"<<endl;
    }




    void showInfo()
    {
        cout << "姓名:" << this->name << ",年龄:" << this->age << endl;
    }
    ~Stu()
    {
        cout << "Stu的析构" << endl;
    }
    bool operator<(const Stu& other) const {
        if (name == other.name) {
            return age < other.age;
        }
        return name < other.name;
    }
};


// 计数器类
template <class T>
class RefCount{

    T * ptr;        //用来指向堆区Stu对象
    int count;      //用来计数

public:
    //构造函数
    RefCount(T* ptr = nullptr)
    {
        this->ptr = ptr;
        if(this->ptr != nullptr)
        {
            this->count = 1;
        }
        else{
            this->count = 0;
        }
    }

    //增加引用计数
    void addRef()
    {
        this->count++;
    }

    //减少引用计数
    int delRef()
    {
        //这里把计数器返回出去的目的是,
        //当减完后,可直接判断计数器,如果为0,就直接释放空间
        //省了一步get_count
        return --this->count;
    }

    //获取引用计数
    int get_count()
    {
        return this->count;
    }



};

template<class T>
class SHARED_ptr{

    T * ptr;        //用来指向堆区Stu对象
    RefCount<T> * refcount; //类中嵌套 类的指针, 用来指向计数器类

public:
    //SHARED_ptr的构造
    SHARED_ptr(T * ptr = nullptr)
    {
        this->ptr = ptr;
        if(this->ptr != nullptr)
        {
            this->refcount = new RefCount<T>(this->ptr);
        }
        else{
            this->refcount = new RefCount<T>();
        }
    }

    //SHARED_ptr的析构
    ~SHARED_ptr()
    {
        //每个对象析构的时候,都让计数器--,并判断计数器是否为0,
        //如果计数器为0了,说明析构的是最后一个对象,那么就释放空间
        if(this->refcount->delRef() == 0){
            delete ptr;
            delete refcount;
            this->ptr = nullptr;
            this->refcount = nullptr;
        }
    }

    //SHARED_ptr的拷贝构造
    SHARED_ptr(const SHARED_ptr& other)
    {
        //如果外类不为空
        if(other.ptr != nullptr)
        {
            //将外类堆地址赋值给本类的指针
            this->ptr = other.ptr;

            //错误理解:将外类的计数器,赋值给本类计数器<<--这种理解是错误的
            //正确理解:将本类的计数器指针,也指向外类计数器的地址
            this->refcount = other.refcount;

            //拷贝构造调用时机是在初始化类对象时,所以本类计数器+1
            this->refcount->addRef();

        }
            //如果外类为空
        else {
            this->ptr = other.ptr;  //将外类堆地址赋值给本类的指针
            this->refcount = other.refcount;    //将外类的计数器,赋值给本类计数器
        }
    }

    //SHARED_ptr的=号运算符重载
    SHARED_ptr& operator = (const SHARED_ptr& other)
    {
        if(this == &other)
        {
            return  *this;
        }

        //外类为空
        if(other.ptr == nullptr)
        {
            //外类空,本类非空
            if(this->ptr != nullptr)
            {
                //本类计数器-1,如果减后计数器为0,
                //说明堆空间没人用了,该回收了
                if(this->refcount->delRef() == 0)
                {
                    delete this->ptr;
                    delete this->refcount;
                    this->ptr = nullptr;
                    this->refcount = nullptr;
                }
            }
            //外类赋值给本类
            this->ptr = other.ptr;
            this->refcount = other.refcount;
        }
            //外类非空
        else {
            //外类非空,本类非空
            if(this->ptr != nullptr)
            {
                //两个类都非空,先对本类进行计数器-1,
                //如果计数器为0了,那就释放堆区资源
                if(this->refcount->delRef() == 0)
                {
                    delete this->ptr;
                    delete this->refcount;
                    this->ptr = nullptr;
                    this->refcount = nullptr;
                }
            }

            //然后外类对本类赋值
            this->ptr = other.ptr;
            this->refcount = other.refcount;

            //赋值后,本类计数器需要+1
            this->refcount->addRef();
        }

        return  *this;
    }

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

    //get方法
    T* get()
    {
        return ptr;
    }

    //指针运算符重载
    T* operator->()
    {
        return ptr;
    }

    //获取引用记数
    int use_count()
    {
        return refcount->get_count();
    }





};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值