在处理异常时,由于要抛出异常,经常导致申请空间未释放,打开的文件未关闭等情况,这时,智能指针便应运而生。
智能指针功能和普通指针最大的区别就在于智能指针在退出堆栈时会自动调用析构函数而不会存在忘记释放空间的问题,而且它任然可以对指针进行赋值、解引用等操作。那就来简单的实现一下智能指针吧。
template
class SharedPtr
{
public:
SharedPtr(T* ptr) //构造函数
:_ptr(ptr), _refcount(new int(1))
{
cout << "construction"<< endl;
;
}
SharedPtr(SharedPtr& sp) //拷贝构造函数
:_ptr(sp._ptr), _refcount(sp._refcount)
{
cout << "copy construction" << endl;
(*_refcount)++;
}
SharedPtr& operator=(SharedPtr& sp) //=运算符重载
{
if (*this != sp)
{
release();
_ptr = sp._ptr;
_refcount = sp._refcount;
(*_refcount)++;
}
return *this;
}
~SharedPtr() //析构函数
{
release();
}
void release() //释放空间在引用计数为1时
{
if (--(*_refcount) == 0)
{
cout << "delete:0x" << _ptr << endl;
del(_ptr);
delete _refcount;
}
}
T& operator*() //使智能指针也可以解引用
{
return *_ptr;
}
T* operator->() //使智能指针也可以使用->
{
return _ptr;
}
protected:
T* _ptr; //指针
int* _refcount;//引用计数
DEL del;//创建一个删除器对象
};
那么那个DEL类又有什么用呢?
DEL的存在是由于编译器并不清楚你申请内存的方式,也就不知道该如何释放他,而你就很有必要告诉编译器。删除器是仿函数的一个应用,仿函数其实是一个类,它实现了operator(),因此调用时看起来就和函数一样,所以叫仿函数。
//四个删除器 分别调用了delete,delete[],free(),和fclose()函数。
template
struct Del
{
void operator()(T* ptr)
{
cout << "delete" << endl;
delete ptr;
}
};
template
struct DelArray
{
void operator()(T* ptr)
{
cout << "delete[]" << endl;
delete[] ptr;
}
};
template
struct Free
{
void operator()(T* ptr)
{
cout << "free" << endl;
free( ptr);
}
};
template
struct Fclose
{
void operator()(T* ptr)
{
cout << "fclose" << endl;
fclose(ptr);
}
};
写的差不多了来测试一下子
void testsharedptr()
{
SharedPtr<int, Del<int>> p1(new int(10));
SharedPtr<int, DelArray<int>> p2(new int[10]);
SharedPtr<FILE, Fclose<FILE>> p3(fopen("test1.txt", "w"));
SharedPtr<int, Free<int>> p4((int*)malloc(10 * sizeof(int)));
SharedPtr<int, Del<int>> p12 = p1;
}
最后看运行结果正如预期,不同的申请方式也对应了不同的释放方式。