c++智能指针shared_ptr的实现

我们想将shared_ptr实现,一定会用到模板类这个功能,并且得分两个类进行实现,Ref主要负责存储引用计数和原始指针,而Shared_ptr部分,将存储Ref指针,这样我们让所有共用一块堆区内存的Shared_ptr对象公用一个Ref指针,我们每析构一次Shared_ptr,就让Ref指针里面的引用计数--,这样就可以实现shared_ptr

全部代码在文章的末尾

下面是Ref指针部分,主要属性为引用计数和原始指针,还有对他们的一些操作函数

class Ref
{
	
	int r_count = 0;//当前资源计数

	T* object = nullptr; //被管理的堆区内存
public:
	Ref(T *target) :object(target)//Ref的构造函数,初始让引用计数为0,创建就对引用计数++
	{
		r_count++;
	}

	//引用计数加1
	inline void increase()
	{
		r_count++;
	}

	//引用计数减一并且判断是否要释放掉原始堆区内存
	inline void reduce()
	{
		r_count--;  //引用计数减一
		if (r_count == 0) //如果引用计数减为0释放被管理的堆区内存和自己
		{
			delete object;
			delete this;
		}
	}
	T *get()//实现get方法获取原始指针
	{
		return object;
	}

	int getCount()//实现use_count()功能
	{
		return r_count;
	}
};

Shared_ptr部分

Shared_ptr我们要实现的功能有以下几点:

  • 无参构造,传递指针构造,拷贝构造,移动构造,拷贝赋值,移动赋值
  • reset()替换对象 reset()销毁对象
  • operator*() operator->()
  • get()获取原始指针
  • use_count 获得引用计数

无参构造,传递指针构造,拷贝构造,移动构造,拷贝赋值,移动赋值

析构函数:

我们每析构一个Shared_ptr指针就让对应的Ref指针对应的Ref内部的引用计数--

~Share_ptr()//调用析构函数,
	{
		if (ref) ref->reduce(); //引用计数减一
	}

构造函数:

调用构造函数时,我们只需新建好一个Ref指针,并且将原指针传给Ref

Share_ptr(T *newP)
	{
		cout << "---------------------调用构造函数-----------------" << endl;
		ref = new Ref<T>(newP);
	}

拷贝构造与移动构造:

我们只需要将原来成员的Ref指针传给新成员的Ref指针,并且让Ref指针对应的引用计数++

Share_ptr(const Share_ptr &other)
	{
		cout << "------------------调用拷贝构造-----------------" << endl;
		this->ref = other.ref;
		if(ref) ref->increase(); //引用计数加1
	}

	Share_ptr( Share_ptr &&other)
	{
		cout << "------------------调用移动构造-----------------"<<endl;
		ref = other.ref;
		other.ref = nullptr;
	}

赋值与移动赋值:

普通赋值我们需要将原来指针的引用计数减一,然后将原来成员的Ref指针传给新成员的Ref指针,并且再次让Ref对应的引用计数加一,为什么不直接让Ref不变呢?是因为如果原指针的引用计数为1,应该调用原指针的析构函数

而移动赋值我们就不需要将原来的指针引用计数++,因为原来的指针的引用计数不需要发生改变

Share_ptr& operator=(const Share_ptr &other)
	{
		cout << "-------------------------调用赋值函数-----------------------"<<endl;
		if (ref)
		{
			ref->reduce();
		}
		ref = other.ref;
		if (ref)
		{
			ref->increase();
		}
		return *this;
	}
	Share_ptr& operator =(Share_ptr &&other)
	{
		cout << "--------------------------调用移动赋值------------------------"<<endl;
		if (ref)
		{
			ref->reduce();
		}
		ref = other.ref;
		other.ref = nullptr;
		return *this;
	}

rest()

rest中我们只需要判断目前的Shared_ptr的Ref指针是否存在,如果存在就让Ref对应的引用计数减一

void reset(T* target)
	{
		if (ref) ref->reduce();
		ref = new Ref<T>(target);
	}
	void reset()
	{
		if (ref) ref->reduce();
		ref = nullptr;
	}

operator*() operator->()

*我们只需要调用Ref的get方法并且对原始指针取*即可

而->则需要判断是否存在Ref指针

T& operator*()
	{
		return *ref->get();
	}
	T* operator->()
	{
		if (ref)
		{  
			return ref->get();
		}
	}

get()

我们就只需要返回Ref的get()方法获取原始指针就可以

T* get()
    {
        return Ref->get();
    }

use_count

我们就只需要返回Ref的ues_count()方法获取引用计数就可以

int use_count()
	{
		if (ref) return ref->getCount();
		else return 0;
	}

全部代码

#pragma once
#include<iostream>
using namespace std;
template<class T>
class Ref
{

	int r_count = 0;//当前资源计数

	T* object = nullptr; //被管理的堆区内存
public:
	Ref(T *target) :object(target)
	{
		r_count++;
	}

	//引用计数加1
	inline void increase()
	{
		r_count++;
	}

	//引用计数减一并且判断是否要释放掉原始堆区内存
	inline void reduce()
	{
		r_count--;  //引用计数减一
		if (r_count == 0) //如果引用计数减为0释放被管理的堆区内存和自己
		{
			delete object;
			delete this;
		}
	}
	T *get()
	{
		return object;
	}

	int getCount()
	{
		return r_count;
	}
};
//共享智能指针需要的方法:
/*
		无参构造,传递指针构造,拷贝构造,移动构造,拷贝赋值,移动赋值
		reset()替换对象 reset()销毁对象
		operator*()  operator->()
		get()获取原始指针
		use_count 获得引用计数
*/
template<class T>
class Share_ptr
{
	Ref<T> * ref = nullptr;
public:
	Share_ptr() = default;
	~Share_ptr()
	{
		if (ref) ref->reduce(); //引用计数减一
	}
	Share_ptr(T *newP)
	{
		cout << "---------------------调用构造函数-----------------" << endl;
		ref = new Ref<T>(newP);
	}
	Share_ptr(const Share_ptr &other)
	{
		cout << "------------------调用拷贝构造-----------------" << endl;
		this->ref = other.ref;
		if(ref) ref->increase(); //引用计数加1
	}

	Share_ptr( Share_ptr &&other)
	{
		cout << "------------------调用移动构造-----------------"<<endl;
		ref = other.ref;
		other.ref = nullptr;
	}
	Share_ptr& operator=(const Share_ptr &other)
	{
		cout << "-------------------------调用赋值函数-----------------------"<<endl;
		if (ref)
		{
			ref->reduce();
		}
		ref = other.ref;
		if (ref)
		{
			ref->increase();
		}
		return *this;
	}
	Share_ptr& operator =(Share_ptr &&other)
	{
		cout << "--------------------------调用移动赋值------------------------"<<endl;
		if (ref)
		{
			ref->reduce();
		}
		ref = other.ref;
		other.ref = nullptr;
		return *this;
	}

	void reset(T* target)
	{
		if (ref) ref->reduce();
		ref = new Ref<T>(target);
	}
	void reset()
	{
		if (ref) ref->reduce();
		ref = nullptr;
	}
	T& operator*()
	{
		return *ref->get();
	}
	T* operator->()
	{
		if (ref)
		{  
			return ref->get();
		}
	}
	int use_count()
	{
		if (ref) return ref->getCount();
		else return 0;
	}
    T* get()
    {
        return Ref->get();
    }
};

  • 3
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值