当前位置: 首页 > news >正文

RAII 示例

下面是一个符合 RAII(Resource Acquisition Is Initialization) 原则的 C++ 示例,它使用智能指针(std::unique_ptr)和 RAII 方式管理资源,而不是手动 try-catch 处理资源释放。


示例:使用 RAII 进行文件管理

错误示例(手动 try-catch 释放资源,容易遗漏释放)
#include <iostream>
#include <fstream>
#include <stdexcept>void writeFile(const std::string& filename) {std::ofstream file(filename);if (!file.is_open()) {throw std::runtime_error("Failed to open file");}try {file << "Hello, RAII!\n";// 可能发生异常throw std::runtime_error("Unexpected error occurred!");} catch (...) {file.close();  // 需要手动关闭,否则可能泄漏throw;  // 重新抛出异常}file.close();  // 需要手动管理
}

问题:

  • 需要手动 close() 文件,容易遗漏(如异常发生时)。
  • 代码冗长,不易维护。

正确示例:使用 RAII 自动管理资源

#include <iostream>
#include <fstream>
#include <stdexcept>void writeFile(const std::string& filename) {std::ofstream file(filename);  // RAII 自动管理文件资源if (!file) {throw std::runtime_error("Failed to open file");}file << "Hello, RAII!\n";  // 如果异常发生,file 会自动关闭if (file.fail()) {throw std::runtime_error("Failed to write to file");}
}  // file 在作用域结束时自动关闭,无需手动管理

改进点:

  • 利用 RAIIstd::ofstream 会在作用域结束时自动关闭文件。
  • 代码更清晰,无需手动 close()
  • 异常发生时,文件句柄仍会被正确释放。

示例:RAII + 智能指针管理资源

#include <iostream>
#include <memory>
#include <stdexcept>class Resource {
public:Resource() { std::cout << "Resource acquired\n"; }~Resource() { std::cout << "Resource released\n"; }void use() { std::cout << "Using resource\n"; }
};void process() {std::unique_ptr<Resource> res = std::make_unique<Resource>();res->use();throw std::runtime_error("Something went wrong!");  // 资源仍会自动释放
}int main() {try {process();} catch (const std::exception& e) {std::cerr << "Caught exception: " << e.what() << "\n";}return 0;
}

优点:

  • 智能指针(std::unique_ptr)管理资源,无需手动 delete
  • 异常安全,即使 throw 发生,资源仍然正确释放。

这样做可以避免裸 try-catch 处理资源释放,让 C++ 自动管理资源,提高代码的安全性和可读性。


两段代码的核心区别在于:第一段代码中的 file.close(); 其实是多余的,手动关闭文件并非必须,因为 std::ofstreamRAII 资源,它的析构函数会自动关闭文件。

解析第一段代码

void writeFile(const std::string& filename) {std::ofstream file(filename);if (!file.is_open()) {throw std::runtime_error("Failed to open file");}try {file << "Hello, RAII!\n";throw std::runtime_error("Unexpected error occurred!");} catch (...) {file.close();  // ❌ 多余!ofstream 在析构时会自动关闭throw;}file.close();  // ❌ 这行代码不会被执行,且也是多余的
}

为什么 file.close(); 是多余的?

  • file局部变量,当 writeFile() 函数的作用域结束时,file 的析构函数会自动调用 close(),无论是正常返回还是抛出异常。
  • 异常发生时catch 处理完异常后,file 仍然会被销毁,析构函数仍会关闭文件。
  • catch 块中的 file.close(); 是显式调用 close(),但它不是必须的,因为 ofstream 的析构函数已经负责了这一点。

解析第二段代码

void writeFile(const std::string& filename) {std::ofstream file(filename);  // RAII 自动管理文件资源if (!file) {throw std::runtime_error("Failed to open file");}file << "Hello, RAII!\n";if (file.fail()) {throw std::runtime_error("Failed to write to file");}
}  // ✅ file 的析构函数会自动关闭文件

为什么这段代码不需要 file.close();

  • file 是局部变量,函数结束时会自动销毁。
  • std::ofstream 的析构函数会自动关闭文件,无需手动 close()

第一段代码的问题

catch 语句中手动 file.close(); 不是错误的,但它是多余的

  • 如果异常发生,catch 语句执行完后,file 仍然会被销毁,其析构函数仍会自动关闭文件。
  • 如果异常未发生,file 在作用域结束时仍然会自动关闭

这就导致 第一段代码的 file.close(); 其实是冗余的,手动调用 close() 没有任何额外的作用。


总结

  • std::ofstreamRAII 资源,不需要手动 close(),它的析构函数会自动关闭文件。
  • 第一段代码手动 close()不必要的,但不会引发错误。
  • 第二段代码更简洁,完全利用了 RAII 机制,是更好的实践。
http://www.xdnf.cn/news/238285.html

相关文章:

  • 2025-03 机器人等级考试四级理论真题 4级
  • Dify添加ollama模型失败:NewConnectionError: Failed to establish a new connection
  • MCP与开源社区的共赢之道:携手推动技术创新
  • GRE隧道
  • Git Stash 详解
  • windows系统常用快捷键(CMD常用命令,DOS常用命令)
  • C++类和对象(中)
  • PostgreSQL中的SSL
  • 设备目录树--个人笔记
  • linux中sigint和sigterm的区别
  • react-11使用vscode开发react相关扩展插件(相关的快捷生成)
  • 开芯课堂丨视觉与4D毫米波前融合感知算法设计
  • [计算机科学#6]:从锁存器到内存,计算机存储的构建与原理
  • 航电系统之网络控制运动技术篇
  • C++Primerplus编程练习 第三章
  • Vue3源码学习-提交限制
  • 标准解读:数据要素安全可信流通技术标准【附全文阅读】
  • 驾驭音质,尽享四通道力量——AXPA17851
  • 若依定时任务
  • 【go】简单问答八股,go的理解,接口,锁,channel
  • 处理vue3热加载后axios的请求重复访问的问题
  • 深入理解C++17中的std::string_view
  • LibAI Lab走进西浦:重塑“AI+建筑”教育
  • 做了数据中台,还需要做数据治理吗?
  • 2025.4.28 Vue.js 学习笔记
  • 饿了么推出骑手AI助手小饿,智能配送再升级
  • 【综述】相位解包裹算法对比分析
  • QML学习:使用QML实现抽屉式侧边栏菜单
  • 融合AI助力医疗提效,华奥系医务系统助力医院数字化升级!
  • 老王说暗网【第8期】攻防演练的盲区?ATO(Account Takeover)攻击风险