智能指针实现
原来的内存管理代码
int main()
{
int *ptr = new(nothrow) int(0); //关闭异常
if(!ptr)
{
cout << "new fails."
return 0;
}
if(!check()) ///有校验 ,抛出异常,每次都得管理内存
{
delete ptr; //释放
ptr = nullptr; //防止空悬指针
throw exception();
}
delete ptr; //释放
ptr = nullptr; //防止空悬指针
return 0;
}
/////////////////////////////////////////////////////////////////////////////////////////////////
使用引用计数,实现智能指针
1.构造函数中计数初始化为1,拷贝构造函数中计数值加1;
2.析构函数中引用计数减一;
3.赋值运算符中,左边的对象引用计数减一,右边的对象引用计数加一;
4.在赋值运算符和析构函数中,如果减一后为0,则调用delete释放对象。
/////////////////////////////////////////////////////////////////////////////////////////////
智能指针即为封装好的,带计数的指针,需要实现 构造函数,拷贝构造,赋值构造,析构
#include <iostream>
using namespace std;
template<class T> //模板类T,智能指针即为封装好的,带计数的指针
class SmartPtr
{
public:
SmartPtr(T *p); //构造函数,参数是普通指针
SmartPtr(const SmartPtr<T> &orig); // 拷贝构造 ,浅拷贝
SmartPtr<T>& operator=(const SmartPtr<T> &rhs); // 赋值操作符号,浅拷贝
~SmartPtr() ; //析构函数
private:
T * ptr; // 指针
int *use_count; // 将use_count声明成指针是为了方便对其的递增或递减操作
};
template<class T>
SmartPtr<T>::SmartPtr(T *p) : ptr(p)
{
try
{
use_count = new int(1); //分配计数内存
}
catch (...)
{
delete ptr;
ptr = nullptr;
use_count = nullptr;
cout << "Allocate memory for use_count fails." << endl;
exit(1); //退出程序
}
cout << "Constructor is called!" << endl;
}
template<class T>
SmartPtr<T>::~SmartPtr()
{
// 只在最后一个对象引用ptr时才释放内存
if (--(*use_count) == 0)
{
delete ptr;
delete use_count;
ptr = nullptr;
use_count = nullptr;
cout << "Destructor is called!" << endl;
}
}
template<class T>
SmartPtr<T>::SmartPtr( const SmartPtr<T> &orig)
{
ptr = orig.ptr;
use_count = orig.use_count;
++(*use_count);
cout << "Copy constructor is called!" << endl;
}
// 重载等号函数不同于复制构造函数,即等号左边的对象可能已经指向某块内存。
// 这样,我们就得先判断左边对象指向的内存已经被引用的次数。如果次数为1,
// 表明我们可以释放这块内存;反之则不释放,由其他对象来释放。
template<class T>
SmartPtr<T>& SmartPtr<T>::operator = (const SmartPtr<T> &rhs)
{
//这句话如果放在最后面,那么 rhs=rhs(计数为1的时候),将会释放内存
++(*rhs.use_count);
// 将左操作数对象的使用计数减1,若该对象的使用计数减至0,则删除该对象
if (--(*use_count) == 0)
{
delete ptr;
delete use_count;
cout << "Left side object is deleted!" << endl;
}
ptr = rhs.ptr;
use_count = rhs.use_count;
cout << "Assignment operator overloaded is called!" << endl;
return *this;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
使用方法
指向单个元素的 智能指针,会有默认内存释放器,也可自己定义
shared_ptr<string> str_point ( new string("jutta"),
// 自定义析构函数,lamada表达式
[](string *p)
{
cout << "delete " << *p << endl;
delete p;
}
);
指向数组元素的 智能指针,需要自己定义内存释放函数
shared_ptr<int> int_point ( new int[10],
// 自定义析构函数,lamada表达式
[](int *p)
{
delete[] p;
}
);
也可以使用unique_ptr的default_delete函数
shared_ptr<int> int_point (new int[10], default_delete <int [] > () );
share_prt与weak_ptr的区别?