C++ 异常安全(Exception Safety)

C++ 异常安全(Exception Safety)

异常安全(Exception Safety) 是指 C++ 代码在发生异常时能否保持正确性,避免资源泄漏和未定义行为

C++ 通过 RAII(资源获取即初始化)智能指针noexcept 关键字 等方式提高异常安全性。


1. 为什么需要异常安全?

如果代码在异常发生时没有正确释放资源,会导致:

  1. 资源泄漏(如内存、文件句柄、锁等)。
  2. 数据不一致(对象状态部分修改,程序逻辑混乱)。
  3. 程序崩溃(因为异常传播到未处理的地方)。

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 + 智能指针 + 强异常安全策略,确保程序健壮性! 🚀

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值