我们想将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();
}
};