RAII与异常安全的关系
RAII是如何与C++异常安全性(强烈保证/基本保证/不抛出保证)相结合的?为什么说RAII是C++异常安全的基石?举例说明不使用RAII时的异常安全问题和使用RAII后的改进。
回答
Yahuda
RAII是异常安全的基石:因为RAII保证资源在对象析构时自动释放,无论控制流如何离开作用域(正常返回、异常栈展开、break/continue/goto)。
异常安全三级保证:
- 不抛出保证(no-fail):操作不抛出异常(如析构函数、swap)
- 强保证(strong):操作失败时不改变状态(类似事务语义——提交则全部成功,失败则回滚)
- 基本保证(basic):操作失败时对象处于有效但不可预测的状态(无资源泄漏)
不使用RAII的典型问题:
void bad() {
Resource* r = new Resource();
do_something(); // 抛异常 -> r泄漏
delete r;
}
使用RAII:
void good() {
auto r = std::make_unique<Resource>();
do_something(); // 抛异常 -> unique_ptr析构释放资源
}
关键原则:构造函数获取资源,析构函数释放资源。异常时栈展开自动调用所有局部对象的析构函数。没有RAII的C++异常安全几乎不可能保证。