自定义 std::unique_ptr 的 deleter 是让指针释放时执行指定逻辑而非仅 delete;支持函数指针、lambda、functor 等可调用类型,需在模板参数中显式声明 deleter 类型。

自定义 std::unique_ptr 的 deleter,核心是让指针在释放资源时执行你指定的逻辑,不只是简单调用 delete。
deleter 的类型和写法
deleter 可以是函数指针、函数对象(functor)、lambda 表达式,或任何可调用类型,只要它接受一个参数(指针类型)且无返回值。
- 函数指针:需提前声明函数,签名形如
void my_deleter(int* p) - lambda:最常用,捕获灵活,适合带状态的清理逻辑(比如记录日志、关闭句柄)
- functor:适合复用、需保存内部状态的场景(如计数器、资源池管理)
基本用法:模板参数显式指定 deleter 类型
必须在 unique_ptr 模板中声明 deleter 类型,否则编译失败:
auto del = [](int* p) {
std::cout << "Deleting: " << *p << "\n";
delete p;
};
std::unique_ptr ptr(new int(42), del);
注意:不能只写 std::unique_ptr 然后传 lambda 构造——类型不匹配。必须把 decltype(del) 显式作为第二个模板参数。
立即学习“C++免费学习笔记(深入)”;
避免手动写 decltype:用 make_unique 的替代方案
C++14 起没有直接支持自定义 deleter 的 make_unique,但可以封装辅助函数:
templateauto make_unique_with_deleter(Deleter&& d) { return std::unique_ptr >( new T(), std::forward (d) ); } // 使用 auto ptr = make_unique_with_deleter ([](int* p) { delete p; });
这样就不需要反复写 decltype,也避免了类型推导错误。
常见实用场景
- 释放 C 风格资源:如
fopen/fclose,用std::unique_ptr - 数组管理:用
std::default_delete替代默认的delete(防止未定义行为) - 共享所有权模拟:deleter 中调用
release()或触发回调,实现“最后释放时才真正销毁” - 调试追踪:deleter 打印地址、计数、校验资源状态,排查泄漏或重复释放
基本上就这些。关键不是“怎么写”,而是想清楚:资源谁分配、谁释放、释放时要做什么——deleter 就是你掌控释放环节的钩子。











