手动实现std::shared_ptr源码

一、Shared_ptr 定义

  1. 从c++11开始,std给我们提供4中智能指针auto_ptr、unique_ptr、shared_ptr 和 weak_ptr,其中最常用的为unique_ptr、shared_ptr,今天我们看下如何用代码实现shared_ptr的基本功能。

  2. 首先share_ptr也是一个类。可以实现多个指针指向同一对象(引用计数),有以下3个特性。

    • 每使用一次,内部引用计数加1;
    • 每析构一次,内部引用计数减1,;
    • 引用计数减为0时,自动释放原生指针所指向的内存。

二、代码实现

重点一、我们知道,std提供的shared_ptr的核心就是引用计数,实现方法可以用指针的方式也可以用全局变量的方式,这里我们用指针的方式。多个shared_ptr对象共用同一个指针(指向引用计数)。

int* count;     //一个指向引用计数器的指针

重点二、 为什么成员运算符(->)的重载返回类型是原生指针的类型?shared_ptr名为指针,其实是类。对一个类采用成员运算符重载,返回值很自然的就是类中的成员了。

所以我们需要运算符重载:-> * &等这几个运算符

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

        //运算符重载:* 实现取值功能
        T& operator*(){
            return *ptr;
        }

完整代码:

#include<iostream>
using namespace std;

template<typename T>
class MySharedPtr{
    public:
        //构造函数1,空指针,计数为0
        MySharedPtr():count(nullptr),ptr(nullptr){}           
        //构造函数2,从原生指针构造
        MySharedPtr(T* p):count(new int(1)),ptr(p){}
        //构造函数3,拷贝构造函数,引用计数器+1,让该对象的指针指向形参对象的指针
        MySharedPtr(const MySharedPtr<T>& another){ 
            ptr = another.ptr;
            ++(*another.count);
            count = another.count;
        }  

        //析构函数,使用引用次数减一,判断引用是否为0,为0的话调用delete
		~MySharedPtr() {                         
			(*count)--;
			if (ptr && *count == 0)
			{
				delete ptr;
				delete count;
                cout << "delete ptr ~" << this << endl;
			}
		}

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

        //运算符重载:* 实现取值功能
        T& operator*(){
            return *ptr;
        }

        //运算符重载:& 实现赋值功能
        MySharedPtr<T>& operator=(MySharedPtr<T>& another){
            if(this == &another)       //解决自赋值问题,如果判断是自赋值,直接返回
                return *this;
            
            ++(*another.count);         //another被指向的对象计数加一        

            if(this->ptr&&--(*this->count)==0){        //如果原来的shared_ptr已经有对象,则让其引用计数减少一,并判断引用是否为0,如果为0,则调用delete释放ptr
                delete this->count;
                delete this->ptr;
                cout << "delete ptr " << this << endl;
            }
            this->ptr = another.ptr;
            this->count = another.count;
            return *this;
        }
       
        int getCount(){                               //计算被引用次数
            return *count;
        }

    private:
        T* ptr;         //一个指向对象的模板指针
        int* count;     //一个指向引用计数器的指针
};

简单测试代码:

int main(){
    //构造函数2
    MySharedPtr<string> pstr(new string("abc"));    //new一个对象
    cout<<"pstr "<<pstr.getCount()<<" "<<*pstr<<endl;
    cout<<endl;
    //构造函数3,拷贝构造
    MySharedPtr<string> pstr2(pstr);
    cout<<"pstr: "<<pstr.getCount()<<" "<<*pstr<<endl;
    cout<<"pstr2: "<<pstr2.getCount()<<" "<<*pstr2<<endl;
    cout<<endl;

    return 0;
}

运行如下:
请添加图片描述

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 5
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

苏克贝塔

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值