1. 异常安全的基本概念与重要性
在C++开发中,异常安全(Exception Safety)是指当程序抛出异常时,系统能够保持一致性状态的能力。这个概念最早由Bjarne Stroustrup在《The C++ Programming Language》中提出,现已成为高质量C++代码的重要指标。
异常安全之所以重要,是因为:
- 资源管理:异常可能导致内存泄漏、文件句柄未关闭等资源问题
- 数据一致性:异常中断正常流程可能导致数据结构处于不一致状态
- 可维护性:异常安全的代码更容易理解和调试
我在实际项目中见过一个典型案例:某金融系统在处理交易时抛出异常,导致账户余额更新了但交易记录未写入,造成了严重的数据不一致。这就是典型的异常安全问题。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 异常安全的三个基本级别
2.1 基本保证(Basic Guarantee)
这是最低级别的异常安全保证,要求:
- 不泄漏任何资源
- 所有对象保持有效状态(即使不是预期状态)
- 程序保持一致性
实现要点:
- 使用RAII管理资源
- 避免裸指针
- 在修改对象状态前进行验证
cpp复制class Account {
std::mutex mtx;
double balance;
public:
void transfer(double amount) {
std::lock_guard<std::mutex> lock(mtx); // RAII保证锁释放
if (balance < amount)
throw InsufficientFunds();
balance -= amount; // 先扣款
// 如果这里抛出异常,余额已变化但转账未完成
}
};
2.2 强保证(Strong Guarantee)
这一级别保证操作要么完全成功,要么完全不发生,保持操作前的状态。实现方式通常包括:
- 先准备所有需要的资源
- 在确保不会抛出异常后再提交更改
- 使用copy-and-swap惯用法
cpp复制void Account::safeTransfer(double amount) {
std::unique_lock<std::mutex> lock(mtx);
double newBalance = balance - amount; // 先计算
if (newBalance < 0)
throw InsufficientFunds();
balance = newBalance; // 原子性赋值
// 此时即使抛出异常,状态也是一致的
}
2.3 不抛保证(No-throw Guarantee)
最高级别的保证,承诺操作不会抛出任何异常。适用于:
- 析构函数
- 内存释放操作
- 简单的getter方法
cpp复制class SimpleBuffer {
char* data;
public:
