在上一篇博客中,我们模拟实现了几种智能指针,这里我们在自己模拟实现的SharedPtr的基础上,分别利用仿函数和函数指针来定制删除器。
为什么要定制删除器呢,如果我们用new开辟空间,那么需要用delete来释放,如果用fopen打开一个文件,那么我们需要用fclose来关闭,同理malloc与free对应,如果不匹配使用,那么程序就有可能会崩溃。
1.利用函数指针的方法
使用模板函数,在SharedPtr中多增加一个函数指针,在传参时多传一个参数函数名,使用函数指针接受,通过函数指针调用对应的函数完成释放空间。
template <class T>
void Delete(T*& p)
{
if (p)
{
delete p;
p = NULL;
}
}
template <class T>
void Free(T*& p)
{
if (p)
{
free(p);
p = NULL;
}
}
void FClose(FILE*& p)
{
if (p)
{
fclose(p);
p = NULL;
}
}
template<class T>
class SharedPtr
{
public:
SharedPtr(T* ptr = NULL, void (*pFun)(T*&) = Delete)//设置默认为delete
: _ptr(ptr)
, _pCount(new int(0))
, _Dptr(pFun)
{
if (_ptr)
*_pCount = 1;
}
SharedPtr(const SharedPtr& sp)
: _ptr(sp._ptr)
, _pCount(sp._pCount)
{
if(_ptr)
(*_pCount)++;
}
SharedPtr& operator=(const SharedPtr& sp)
{
if (this != &sp)
{
_Realse();
_ptr = sp._ptr;
_pCount = sp._pCount;
if (*_pCount)
(*_pCount)++;
}
return *this;
}
~SharedPtr()
{
_Realse();
}
private:
void _Realse()
{
if (_pCount && --(*_pCount) == 0)
{
_Dptr(_ptr);
_ptr = NULL;
delete _pCount;
_pCount = NULL;
}
}
private:
T* _ptr;
int* _pCount;
void (*_Dptr)(T*&);
};
int main()
{
SharedPtr<int> sp1(new int(5));
SharedPtr<FILE> sp2(fopen("1.txt", "r"), FClose);
SharedPtr<double> sp3((double*)malloc(10), Free);
return 0;
}
2. 利用仿函数
使用模板类对释放空间的函数封装,在SharedPtr的模板参数列表中多增加一个参数,利用仿函数完成对空间的释放。
template <class T>
class Delete
{
public:
void operator()(T*& p)
{
if (p)
{
delete p;
p = NULL;
}
}
};
template <class T>
class Free
{
public:
void operator()(T*& p)
{
if (p)
{
free(p);
p = NULL;
}
}
};
class Fclose
{
public:
void operator()(FILE*& p)
{
if (p)
{
fclose(p);
p = NULL;
}
}
};
template<class T, class Dx = Delete<T>>
class SharedPtr
{
public:
SharedPtr(T* ptr = NULL)
: _ptr(ptr)
, _pCount(new int(0))
{
if (_ptr)
*_pCount = 1;
}
SharedPtr(const SharedPtr& sp)
: _ptr(sp._ptr)
, _pCount(sp._pCount)
{
if (_ptr)
(*_pCount)++;
}
SharedPtr& operator=(const SharedPtr& sp)
{
if (this != &sp)
{
_Realse();
_ptr = sp._ptr;
_pCount = sp._pCount;
if (*_pCount)
(*_pCount)++;
}
return *this;
}
~SharedPtr()
{
_Realse();
}
T* operator->()
{
return _ptr;
}
T& operator*()
{
return *_ptr;
}
private:
void _Realse()
{
if (_pCount && --(*_pCount) == 0)
{
Dx()(_ptr);
//delete _ptr;
_ptr = NULL;
delete _pCount;
_pCount = NULL;
}
}
private:
T* _ptr;
int* _pCount;
};
int main()
{
SharedPtr<int> sp1(new int(5));
SharedPtr<FILE, Fclose> sp2(fopen("1.txt", "r"));
SharedPtr<double, Free<double>> sp3((double*)malloc(10));
return 0;
}