题目
使用智能指针管理文件资源并实现自定义清理
信息
- 类型:问答
- 难度:⭐⭐
考点
智能指针应用, 资源管理, 自定义删除器, 异常安全
快速回答
使用std::unique_ptr配合自定义删除器安全管理文件资源:
- 声明形式:
std::unique_ptr<FILE, decltype(&fclose)> filePtr(fopen("data.txt", "r"), fclose) - 自动调用
fclose释放资源 - 确保异常安全,避免资源泄漏
- 支持移动语义,禁止拷贝
问题背景
在C++中管理文件资源时,传统方式需要手动调用fclose,若在打开和关闭之间发生异常或提前返回,会导致资源泄漏。智能指针配合自定义删除器可解决此问题。
解决方案
#include <memory>
#include <cstdio>
void processFile() {
// 定义带自定义删除器的unique_ptr
std::unique_ptr<FILE, decltype(&fclose)> filePtr(
fopen("data.txt", "r"),
fclose
);
if (!filePtr) throw std::runtime_error("File open failed");
// 使用文件(示例:读取字符)
int ch = fgetc(filePtr.get());
// 无需显式调用fclose - 自动释放
}
原理说明
- 自定义删除器:通过第二个模板参数指定清理函数(此处为
fclose) - RAII机制:文件打开即初始化资源,离开作用域时自动调用删除器
- 异常安全:即使
fgetc抛出异常,文件仍会被正确关闭
最佳实践
- 优先使用
std::fstream等C++标准库文件工具 - 必须使用C文件API时,采用此模式封装
- 对于数组资源:
std::unique_ptr<int[], void(*)(int[])> - C++17起可简写:
std::unique_ptr filePtr(fopen(...), fclose)
常见错误
- 错误1:直接赋值
FILE*给普通智能指针(类型不匹配) - 错误2:删除器签名不匹配(如使用
delete而非fclose) - 错误3:在资源转移后重复使用原始指针
扩展知识
std::shared_ptr自定义删除器:构造函数中指定,不影响类型std::shared_ptr<FILE> sp(fopen(...), fclose)- Lambda删除器:处理复杂清理逻辑
auto deleter = [](FILE* f) { /* 多步清理 */ }; - 对比
finally:RAII相比try-finally更简洁安全