unique_ptr是stl定义的一种智能指针,利用C++的RAII机制进行内存管理,防止内存泄漏。除了内存之外,unique_ptr还可以用来管理其他资源,如FILE,代码如下:
#include <cstdio>
#include <memory>
//文件句柄关闭仿函数
struct FileCloseHandle {
void operator() (FILE *pf) {
if (pf != nullptr) {
fclose(pf);
}
}
};
//定义文件句柄管理类型
typedef std::unique_ptr<FILE, FileCloseHandle> FileGuard;
int main(int argc, char **argv)
{
FileGuard fg(fopen("a.txt", "w"));
if (fg.get() == nullptr) {
fprintf(stderr, "failed to open a.txt !\n");
return 1;
}
fprintf(fg.get(), "hello world !\n");
return 0;
}
FileCloseHandle是一个仿函数,用于释放文件句柄;FileGuard使用unique_ptr定义了文件句柄自动释放的类型。FileGuard为什么能够实现文件句柄的自动释放?可以看下unique_ptr的定义。
template <class _Tp, class _Dp = default_delete<_Tp> >
class unique_ptr {
......
};
通过unique_ptr的定义(如下),其模板参数有两个 :_Tp为对象的类型;_Dp为对象的释放方法。在unique_ptr对象生命周期结束时,通过调用_Dp释放资源。默认的释放方法为default_delete,是一个仿函数,其通过delete释放指针。定义如下(非全部代码):
//用于释放单个指针
template <class _Tp>
struct default_delete {
template <class _Up>
default_delete(const default_delete<_Up>&,
typename enable_if<is_convertible<_Up*, _Tp*>::value>::type* =
0) _NOEXCEPT {}
void operator()(_Tp* __ptr) const _NOEXCEPT {
delete __ptr;
}
};
//用于释放数组指针
template <class _Tp>
struct default_delete<_Tp[]> {
private:
template <class _Up>
struct _EnableIfConvertible
: enable_if<is_convertible<_Up(*)[], _Tp(*)[]>::value> {};
public:
template <class _Up>
default_delete(const default_delete<_Up[]>&,
typename _EnableIfConvertible<_Up>::type* = 0) _NOEXCEPT {}
template <class _Up>
typename _EnableIfConvertible<_Up>::type
operator()(_Up* __ptr) const _NOEXCEPT {
delete[] __ptr;
}
};
通过default_delete的定义,可以看出:
1.定义一个释放仿函数类型,必须实现operator()(T *ptr)
2.使用malloc申请的内存,必须使用自定义释放函数