删除器
很多时候我们都用new来申请空间,用delete来释放。库中实现的各种智能指针,默认也都是用delete
来释放空间,但是若我们采用malloc申请的空间或是用fopen打开的文件,这时我们的智能指针就无法
来处理,因此我们需要为智能指针定制删除器,提供一个可以自由选择析构的接口,这样,我们的智能
指针就可以处理不同形式开辟的空间以及可以管理文件指针。
自定义智能指针的方式有两种,函数指针与仿函数(函数对象)。原理为利用RAII技术对类对象进行托管,在RAII类中定义指向类对象的指针以及删除器(函数指针,指向自定义的类对象或者函数入口地址均可),同时重载相关运算符。
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <iostream>
#include <functional>
using std::cout;
using std::endl;
using std::string;
using std::function;
//测试类
class Point
{
public:
Point(int x, int y)
: _ix(x), _iy(y)
{
cout << "Point(int,int)" << endl;
}
~Point() { cout << "~Point()" << endl; }
void print() const {
cout << "(" << _ix << "," << _iy << ")" << endl;
}
private:
int _ix, _iy;
};
class Foo
{
public:
Foo() : _a(1) { cout << "Foo()" << endl; }
~Foo() { cout << "~Foo()" << endl; }
private:
int _a = 1;
};
//默认删除器,类形式
template <class T>
struct DefaultDeleter
{
void operator()(T* p)
{
if (p)
{
delete p;
p = nullptr;
cout << "DefaultDeleter operator()(T* p)" << endl;
}
}
};
//对文件指针指定回收方式,函数形式
void MyfpCloser(FILE *fp)
{
if (fp)
{
fclose(fp);
cout << "void MyfpCloser(FILE *fp)" << endl;
}
};
//智能指针删除器部分
template <class T>
class RAII
{
public:
RAII(T* p, function<void(T*)> del = DefaultDeleter<T>()) : _p(p), _deleter(del) {}
~RAII() {
if (_p)
{
_deleter(_p);
_p = nullptr;
}
}
T* get() { return _p; }
//重载相关运算符
T* operator->() { return _p; }
T& operator*() { return *_p; }
//唯一托管
RAII(const RAII&) = delete;
RAII& operator=(const RAII&) = delete;
private:
T* _p;
//函数指针,可用实例化的对象或者函数入口地址赋值。
function<void(T*)> _deleter;
};
void test()
{
RAII<Point> raii(new Point(1, 1));
raii->print();
(*raii).print();
/*
结果
Point(int,int)
(1,1)
(1,1)
~Point()
DefaultDeleter operator()(T* p)
*/
}
void test1()
{
//可通过模版的第二个参数,或者构造函数的第二个参数初始化删除器。
//RAII<FILE, MyfpCloser> fp(fopen("wuhan.txt", "a+"));
RAII<FILE> fp(fopen("wuhan.txt", "a+"), MyfpCloser());
string msg = "hello world\n";
fwrite(msg.c_str(), 1, msg.size(), fp.get());
//结果 void MyfpCloser(FILE *fp)
}
int main(void)
{
//test();
test1();
return 0;
}