实现智能指针
智能指针为了解决C/C++中动态内存的泄漏问题,这通常是由于程序忘记释放动态内存或者程序提前结束导致动态内存无法释放。
RAII
RAII (Resource Acquire Is Initlaziation) 资源获取即初始化:其利用C++中对象的特性,即当一个对象脱离其作用域后,对象将自动调用析构函数完成释放。那么将资源的申请和释放对应于对象的构造和析构函数中,即可完成对资源的智能化管理。
引用计数
对于动态内存的管理,若该内存为多个对象所使用的动态内存,那么通常采取引用计数的方式来管理该动态内存,即当引用计数变为0时,需要释放动态内存,引用计数随着智能指针对象之间的拷贝和赋值= 而发生改变。
共享智能指针shared_pointer的实现
每一个智能指针对象内部包含两个数据成员:
①int指针(指向动态内存区域)
②int 指针(指向引用计数区域)
该部分不能为int类型,否则不能被各个对象所共享,同时也不能为类的静态变量
代码实现
构造函数
private:
int* ptr; //指向共享动态内存区域
int* use_count_ptr; //指向引用计数的指针(确保不同对象引用到同一片区域)
public:
m_pointer()
{
ptr = NULL;
use_count_ptr = NULL;
}
m_pointer(int* _ptr)
{
if (_ptr)
{
ptr = _ptr;
use_count_ptr = new int(1); //初始化创建引用计数区域 大小为1
}
else
{
ptr = NULL;
use_count_ptr = NULL;
}
}
拷贝构造函数
m_pointer(m_pointer& other)
{
//拷贝构造函数
if (other.ptr)
{
ptr = other.ptr;//引用到同一片地址区域
use_count_ptr = other.use_count_ptr;
*(use_count_ptr)= *(use_count_ptr)+1;//对应引用计数增加
}
else
{
ptr = NULL;
use_count_ptr = NULL;
}
}
重载赋值=操作符
注意赋值操作,需要先把自身引用的资源计数-1,如果是最后一个引用的,还需要释放对应动态内存
void operator=(m_pointer& other)
{
if (ptr) //解开自己本身存引用的动态内存
{
*(use_count_ptr) = *(use_count_ptr)-1;;//对应引用计数减1
if (*use_count_ptr == 0) //如果是最后一个引用的需要完成释放
{
delete ptr;
delete use_count_ptr;
ptr = NULL;
use_count_ptr = NULL;
}
}
if (other.ptr)
{
ptr = other.ptr;
use_count_ptr = other.use_count_ptr;
*(use_count_ptr) = *(use_count_ptr)+1;; //增加引用计数量
}
}
使用方法与析构函数
~m_pointer()
{
//析构共享指针对象
*(use_count_ptr) = *(use_count_ptr)-1;;//对应引用计数减1
if (*use_count_ptr == 0) //最后一个还要完成释放
{
delete ptr;
delete use_count_ptr; //释放两个动态区域
}
}
int* get_pointer()
{
return ptr;
}
int get_usecount()
{
if (use_count_ptr == NULL)
return -1;
else
return *use_count_ptr;
}
析构函数中将引用的计数减1,同时如果是最后一个引用的,那么需要释放动态内存区域
易错点
①赋值操作需要先完成自身原先资源的断连
②释放资源时,对应的引用计数区域也需要释放
③引用计数区域也为动态内存 new int(1) 确保被多个智能指针对象访问到