std::unique_ptr自定义删除器通过可调用对象替换默认delete行为,支持函数指针、lambda、函数对象三种方式,需在模板参数中显式声明类型。

std::unique_ptr 自定义删除器的核心原理
默认情况下,std::unique_ptr 使用 delete(对单个对象)或 delete[](对数组)释放资源。但很多场景下需要更精细的控制:比如关闭文件句柄、释放非堆内存、调用 C API 的清理函数、或配合特定内存池。这时就要通过自定义删除器(deleter)来替换默认行为。
三种常见自定义删除器写法
删除器本质是一个可调用对象(函数对象、lambda、函数指针),类型需在 unique_ptr 模板参数中显式声明,否则编译失败:
-
函数指针方式:适合简单、复用性强的清理逻辑
void close_file(FILE* f) { if (f) fclose(f); }
std::unique_ptrfp(fopen("log.txt", "w"), close_file); -
lambda 表达式(需捕获为空,且用 decltype 推导类型):适合轻量、局部逻辑
auto deleter = [](int* p) { std::cout << "freeing: " << *p << "\n"; delete p; };
std::unique_ptrptr(new int(42), deleter); -
仿函数类(重载 operator()):适合带状态或复杂逻辑
struct CustomDeleter { void operator()(MyResource* r) const { r->cleanup(); delete r; } };
std::unique_ptrres(new MyResource(), CustomDeleter{});
删除器与内存布局和性能的关系
删除器类型影响 unique_ptr 对象大小:无状态删除器(如函数指针、空 lambda、无成员的 struct)通常不增加体积;有状态删除器(如含成员变量的仿函数)会让 unique_ptr 占用额外空间。若对内存敏感,优先选无状态方案。另外,删除器调用是 inline 友好的,现代编译器基本能完全内联,性能开销可忽略。
实用技巧:数组 + 自定义删除器的正确写法
不要直接用 std::unique_ptr 配合普通 delete —— 它默认调用 delete[],但若资源不是 new[] 分配的(如 malloc 或 mmap),必须自定义。例如管理 malloc 分配的内存:
立即学习“C++免费学习笔记(深入)”;
auto free_deleter = [](void* p) { free(p); };
std::unique_ptr buf(static_cast(malloc(1024)), free_deleter); 注意:此时不能使用 operator[] 的安全索引(因为类型是 char* 而非 char[]),但可通过 .get() 获取裸指针安全访问。











