- 参考
- 1.内存泄漏,申请的资源没有被释放
- 2.多重释放,引起程序崩溃
智能指针引用计数的原理分析
- 当利用智能指针托管从堆上申请的资源的时候,使智能指针指向这个内存,并再申请一个用于计数的资源,用于管理引用该资源的次数
实现细节
- 智能指针是一个类,使用RAII思想,在构造函数里面申请资源,在析构函数中回收资源。在智能指针中主要就是对申请资源和引用计数是维护
- 需要进行运算符重载,让智能指针使用起来像普通指针一下
- 注意->重载会传递
- 智能指针对任何类型都可以使用,所以它应该是一个模板
类内细节
数据成员
- 为了管理资源,所以需要2个数据成员,引用计数是指针的形式,这可以让所有引用该资源的智能指针共享
addReference()
:当为nullpter时,创建引用计数资源,并初始化为1;否则,引用计数加1。void addReference() { if (m_refCount) { (*m_refCount)++; } else { m_refCount = new int(0); *m_refCount = 1; } }
void removeReference()
:引用计数减一,当变为0时,释放所有资源void removeReference() { if (m_refCount) { (*m_refCount)--; if (*m_refCount == 0) { delete m_refCount; delete m_pointer; m_refCount = 0; m_pointer = 0; } } }
引用计数变换的情况
| 构造函数| 拷贝构造函数 |拷贝赋值函数| 析构
|—-|—-|—-|—-
| 托管资源 | 托管资源 | 左值removeRerence | removeRerence|
| addReference | 托管引用计数 | 托管资源 ||
| | addReference | 托管引用计数 ||
| | | addReference| |
智能指针实现
#include <iostream>
using namespace std;
template<typename T>
class shared_Ptr
{
public:
shared_ptr():m_pointer(nullptr),m_refCount(nullptr){}
shared_Ptr(T* adpotTarget):m_pointer(adoptTarget){addReference();}
shared_Ptr(const shared_Ptr<T>& copy):m_pointer(copy.m_pointer),m_refCount(copy.m_refCount){addReference();}
shared_Ptr<T>& operator=(const shared_Ptr<T>& that)
{
if(this != &that)
{
removeRefrence();
m_pointer = that.m_pointer;
m_refCount = that.m_refCount;
addReference();
}
return *this;
}
shared_Ptr(const shared_Ptr<T>&& copy):m_pointer(copy.m_pointer),m_refCount(copy.m_refCount){copy = nullptr}
shared_Ptr<T>& operator=(const shared_Ptr<T>&& that)
{
if(this != &that)
{
m_pointer = that.m_pointer;
m_refCount = that.m_refCount;
that = nullptr;
}
return *this;
}
~shared_Ptr(){removeRefrence();}
bool operator==(const shared_Ptr<T>& that)
{
return this->m_pointer == that.m_pointer;
}
bool operator!=(const shared_Ptr<T>& that)
{
return this->m_pointer != that.m_pointer;
}
T& operator*() const
{
return *m_pointer;
}
T* operator->() const
{
return m_pointer;
}
int getReferenceCount()
{
if(m_reference)
return *m_refCount;
else
return -1;
}
protected:
void addReference()
{
if(!m_refCount)
{
m_refCount = (size_t*)malloc(sizeof(size_t));
m_refCount = 0;
}
(*m_refCount)++;
}
void removeRefrence()
{
if(!m_refCount) return;
(*m_refCount)--;
if((*m_refCount) == 0)
{
delete m_pointer;
delete m_refCount;
m_pointer = nullptr;
m_reference = nullptr;
}
}
private:
T* m_pointer;
size_t* m_refCount;
};