异常安全性
异常安全保证有 3 种:
(a) 基本保证:保证不会发生资源泄露,即使操作失败;但是状态可能发生改变。
(b) 强保证:事务提交 / 回滚语义 。即使操作失败也不会导致程序状态改变。
(c) 无失败保证:不允许失败发生。即绝对不会抛异常。
准则:函数应该总是支持它所能支持的最强的异常安全保证,但是前提是不能给那些并不需要该保证的调用者带来额外的开销。
准则:永远不要允许析构函数 (deconstruct) 、释放操作 (deallocation) 和 swap() 函数抛出异常,否则的话,就没法安全且可靠地进行资源清理了。这是事务编程的基本前提,没有这些保证,无法确保事务提交和回滚不会失败。
编写异常安全代码的几条建议:
1) 使用“资源获取即初始化 (RAII ,特指 C++ 的构造和析构函数 ) ”惯用法来管理资源的所有权。如果获取失败,就释放资源,这可以防止资源泄露,还可以防止未初始化错误。
2) 使用“先在一旁将所有的事情做完,然后再通过不抛异常的操作来提交整个任务 ”的手法,避免在不确定所有操作能否成功的情况下贸然去改变对象的内部状态。这就是事务性编程,常用于保证强保证。
3) 尽量使用“单一职责的类或函数”。完成多件事情的函数是很难(无法)实现强异常保证的。比如 stack 的 pop 具有取值和出栈两功能,由于 stack 可以用于存储对象(临时变量),而对象 ( 非内置类型 ) 的任何操作 ( 对外接口或运算重载 ) 都是可能抛异常的 ,要实现异常安全非常困难。
参考书:Exceptional C++, Exceptional C++ Style