C++ 异常安全(Exception Safety)
异常安全(Exception Safety) 是指 C++ 代码在发生异常时能否保持正确性,避免资源泄漏和未定义行为。
C++ 通过 RAII(资源获取即初始化)、智能指针、noexcept 关键字 等方式提高异常安全性。
1. 为什么需要异常安全?
如果代码在异常发生时没有正确释放资源,会导致:
- 资源泄漏(如内存、文件句柄、锁等)。
- 数据不一致(对象状态部分修改,程序逻辑混乱)。
- 程序崩溃(因为异常传播到未处理的地方)。
2. 异常安全的 4 级别
C++ 异常安全保证 可分为 4 个级别:
| 级别 | 保证内容 | 示例 |
|---|---|---|
| 1. 无异常安全(No Guarantee) | 可能导致资源泄漏、程序崩溃 | malloc()、裸指针 |
| 2. 基本保证(Basic Guarantee) | 对象处于有效状态,但数据可能不一致 | 普通 std::vector 操作 |
| 3. 强异常安全(Strong Guarantee) | 异常发生时状态回滚,数据不会丢失 | std::swap() |
| 4. 无异常抛出(No-Throw Guarantee) | 保证不会抛出异常 | std::vector::size() |
3. 如何编写异常安全代码
✅ 1. 使用 RAII(资源获取即初始化)
RAII(Resource Acquisition Is Initialization) 通过构造/析构函数管理资源,避免手动 delete。
#include <iostream>
#include <memory>
class FileHandler {
FILE* file;
public:
FileHandler(const char* filename) { file = fopen(filename, "r"); }
~FileHandler() { if (file) fclose(file); } // ✅ 资源自动释放
};
📌 即使 FileHandler 构造失败,fclose() 仍会在析构时正确执行,防止文件泄漏。
✅ 2. 使用 std::unique_ptr 避免 new/delete
std::unique_ptr<int> ptr(new int(10)); // ✅ 自动释放内存
📌 避免 new/delete,防止内存泄漏,即使发生异常。
✅ 3. 使用 try/catch 捕获异常
try {
throw std::runtime_error("Something went wrong!");
} catch (const std::exception& e) {
std::cout << "Caught: " << e.what() << std::endl;
}
📌 捕获异常,避免程序崩溃。
✅ 4. 提供 “强异常安全” 机制
使用 临时对象 + std::swap() 进行 事务式提交,确保异常发生时对象状态不变:
#include <vector>
void safePush(std::vector<int>& vec, int value) {
std::vector<int> temp = vec; // ✅ 备份原数据
temp.push_back(value);
std::swap(vec, temp); // ✅ 异常发生时 `vec` 仍然保持原状态
}
📌 即使 push_back(value) 失败,vec 仍然是完整的,不会丢失原数据。
✅ 5. 使用 noexcept 限制异常传播
void safeFunc() noexcept { // ✅ 保证不会抛出异常
std::cout << "No exception here\n";
}
📌 noexcept 提示编译器优化,并防止异常传播到 std::terminate() 崩溃程序。
4. 关键总结
| 方法 | 作用 | 适用于 |
|---|---|---|
| RAII | 自动管理资源,防止泄漏 | 文件、内存、锁 |
| 智能指针 | 自动释放 new 分配的资源 | 动态内存管理 |
try/catch | 捕获异常,防止崩溃 | 所有可能失败的操作 |
| 强异常安全(事务回滚) | 保证异常发生时数据完整 | 容器操作、文件写入 |
noexcept | 防止异常传播,提高性能 | 不应该抛异常的函数 |
🚀 C++ 异常安全代码要遵循:RAII + 智能指针 + 强异常安全策略,确保程序健壮性! 🚀
192

被折叠的 条评论
为什么被折叠?



