一. 内容
异常安全有两个条件,当异常被抛出时,带有异常安全的函数会:
不泄漏任何资源
不允许数据败坏
泄漏资源的问题可以通过条款13获得解决,我们可以专注于解决数据败坏的问题
异常安全函数提供以下三个保证之一:
基本承诺:如果异常被抛出,程序内的任何事物仍然保持在有效状态之下。没有任何对象或者数据结构因此被破坏。
强烈保证:如果异常被抛出,程序状态不改变。调用这样的函数有这样的认知:如果函数成功,就是完全成功,如果函数失败,程序状态会回到调用函数之前的状态。
不抛掷保证:承诺绝不抛出任何异常,因为它们总是能够完成它们原先承诺的功能。
异常安全代码必须提供以上三种保证之一。除非你天才般的需求分析团队确认你的应用程序有泄漏资源并且在执行过程中带着败坏数据的需要。
有一个一般化的策略可以使得代码获得强烈保证:copy and swap。原则很简单,为你打算修改的对象提供一份副本,然后在副本上做一切必要的修改,若有任何修改动作抛出异常,原对象保持原状态不变。待所有改变都成功后,再将修改过的那个副本和原对象在一个不抛出异常的操作中进行置换(swap)。
copy and swap 策略是对对象状态做出全有,全无改变的一个很好的方法,但一般而言,它并不保证整个函数都具有强烈的异常安全保证。比如:
void fun(){
copyAndSwap();
fun1();
fun2();
//...
}
假如很显然,如果fun1,fun2的异常安全性比 copy and swap低,就很难让整个 fun 成为强烈异常安全。问题其实出在连带影响,如果函数只操作局部性状态,便可以相对容易获得强烈异常安全性。
copy and swap 的关键在于复制对象和置换操作,这其中的代价可能是巨大的,所以请根据自己的实际情况对代码进行异常安全保证。当然记住一点,整个系统的异常安全保证取决于最低的异常安全保证函数。
二. 总结
异常安全函数(Exception-safe functions)即使发生异常也不会泄漏资源或允许任何数据结构败坏。这样的函数区分成三种可能的保证:基本型,强烈型,不抛异常型。
强烈保证往往能够以 copy-and-swap 实现出来,但强烈保证并非对所有函数都可实现或具备现实意义。
函数提供的异常安全保证通常最高只等于其所调用之各个函数的异常安全保证中的最弱者。