C++中如何用智能指针指向std::ifstream或std::cin?
实现方案
核心前提:std::cin是标准库管理的全局流对象,生命周期全局有效,禁止手动释放;自行创建的std::ifstream实例需要保证作用域结束时正确关闭析构。使用智能指针改写时必须配置自定义删除器,避免误删全局对象触发未定义行为。
栈上管理文件流的写法
和原代码的变量定义逻辑一致,std::ifstream实例依然声明在栈上,出作用域自动析构,智能指针只做统一接口转发,配置空删除器不做任何释放操作:
#include <fstream> #include <iostream> #include <memory> #include <string> int main(int argc, char const* argv[]) { // 智能指针指定自定义删除器,默认初始化为空,删除器为空操作 std::unique_ptr<std::istream, void(*)(std::istream*)> in_stream( nullptr, [](std::istream*) {} ); std::ifstream file; if (argc > 1) { file.open(argv[1]); if (!file.is_open()) { return -1; } in_stream.reset(&file); } else { in_stream.reset(&std::cin); } // 后续读取逻辑完全统一,和裸指针的调用方式一致 std::string content; while (std::getline(*in_stream, content)) { std::cout << content << '\n'; } return 0; }
智能指针持有文件流所有权的写法
如果不想在外层单独声明栈上的std::ifstream变量,可以在读取文件时直接在堆上创建文件流实例,把所有权完全交给智能指针,针对不同输入源匹配对应的删除逻辑:
#include <fstream> #include <iostream> #include <memory> #include <string> int main(int argc, char const* argv[]) { std::unique_ptr<std::istream, void(*)(std::istream*)> in_stream( nullptr, [](std::istream*) {} // 默认空删除器,适配cin的无所有权场景 ); if (argc > 1) { auto file = std::make_unique<std::ifstream>(argv[1]); if (!file->is_open()) { return -1; } // 移交文件流所有权,替换删除器确保堆上实例能被正确释放 in_stream = { file.release(), [](std::istream* p) { delete static_cast<std::ifstream*>(p); } }; } else { in_stream.reset(&std::cin); } // 统一读取逻辑和之前无差异 std::string content; while (std::getline(*in_stream, content)) { std::cout << content << '\n'; } return 0; }
注意事项
- 绝对不要用默认删除器的
std::unique_ptr<std::istream>直接持有&std::cin,否则智能指针析构时会delete全局对象,触发重复析构的未定义行为。 - 原本的裸指针写法本身没有内存安全问题,因为裸指针没有持有所有权,只是做接口转发,是否要换成智能指针可以根据项目编码规范决定。
内容的提问来源于stack exchange,提问作者bigyihsuan
相关产品推荐
相关产品推荐

