一、 shared_ptr的模拟实现
我在之前的博客《智能指针》中有说过shared_ptr的原理,那么这篇博客,我们模拟实现一个shared_ptr,让大家能更好的理解它的原理。
include<mutex> //这个头文件是用来使用互斥锁
template<class T>
class Shared_ptr
{
public:
//构造函数
Shared_ptr(T* _ptr = nullptr)
:ptr(_ptr)
, pcount(new int(1))
, pmutex(new mutex)
{}
//该函数是为了对引用计数减1
void Release()
{
bool flag = false;
//因为引用计数是一个临界资源,所以当有多个线程使用它时,可能会出现问题,
//所以用互斥锁来保证数据的安全
pmutex->lock(); //加锁
if (--(*pcount) == 0) //如果此时引用计数为0,说明应该要销毁
{
delete ptr;
delete pcount;
//delete pmutex; 因为此时我们还要使用互斥锁,所以还不能销毁,所以设置一个标志位
flag = true;
}
pmutex->unlock(); //解锁
if (flag == true)
delete pmutex;
}
//只用来对引用计数加1
void AddCount()
{
pmutex->lock(); //加锁
(*pcount)++;
pmutex->unlock(); //解锁
}
~Shared_ptr()
{
Release();
}
//拷贝构造
Shared_ptr(Shared_ptr<T>& sp)
:ptr(sp.ptr)
,pcount(sp.pcount)
,pmutex(sp.pmutex)
{
AddCount();
}
//赋值运算符重载
SharedPtr<T>& operator=(const SharedPtr<T>& sp)
{
if (ptr != sp.ptr)
{
// 释放管理的旧资源
Release();
// 共享管理新对象的资源,并增加引用计数
ptr = sp.ptr;
pcount = sp.pcount;
pmutex = sp.pmutex;
AddRefCount();
}
return *this;
}
private:
T* ptr; //指向被管理的资源
//引用计数虽然是存在于每一个对象中,但是实际上它是跟随着对象所管理的资源
//的,因此要把它设置为指针,这样每个对象可以通过这个指针来共享同一块空间。
//都可以对这个引用计数进行操作
int* pcount; //引用计数
mutex* pmutex; //互斥锁
};