C++异常安全性 - 开发学习中的点点滴滴

来源:百度文库 编辑:神马文学网 时间:2024/04/27 16:10:23

C++异常安全性

星期三, 七月 20. 2005    以前从来不在代码中使用C++的异常机制,一是觉得对效率影响太大,二是自己对异常安全性实在是一窍不通,想用也不敢用。
    看完《exceptional C++》关于异常部分的讨论,才突然有一种豁然开朗的感觉,原来,写出异常安全的代码不是一定要写那些让我浑身不爽的try{...}catch(...){...}代码的
    首先,需要弄清楚两个基本概念:异常安全性保证和异常中立性。异常安全性保证就是说你的代码在发生异常时能提供什么样的保证,它又分为三个等级:基本安全保证、强烈安全保证和无异常抛出保证。基本安全保证指异常发生时你的代码不会发生资源泄露,这样能保证最基本的安全性;强烈安全保证指你的代码满足“提交或回退语义”,即要么完全执行成功提交,要么发生异常回退到代码执行前的状态;无异常抛出保证不是指你在代码中处理掉所有抛出的异常,使其不向外传播,而是指你的代码在任何情况下都不可能引发任何异常,这是最强的异常安全保证。而异常中立性是指当你的代码(包括你调用的代码)引发异常时,这个异常能保持原样传递到外层调用代码。一段代码要具有异常安全性,必须同时具有异常中立性和某个级别的异常安全性保证(这个级别也就是你代码异常安全性的程度了)。
    对一些简单的代码当然是希望其满足无异常抛出保证了,如果不行,就要尽量满足强异常安全保证,这里有一些原则和技巧,总的来说,就是1、异常安全性是在设计时就必须考虑的,它将直接影响设计决策;2、确认所有可能引发异常的代码都安全执行了再执行那些会改变当前状态的代码;3、优先满足内聚性,尽量让你的函数只完成一件必要工作。所以说,写下 fuc(a++,b); 这样的代码绝对是不行的,要写成 fuc(a,b); ++a; 。
    所以我们现在可以明白为什么STL里面很多容器pop方法仅仅弹出元素而不返回,为什么每个标准容器都提供swap方法,为什么STL里面有时候会看到重载operator=参数是传值而不是传引用,为什么auto_ptr的赋值语义是所有权转换而不是深拷贝,答案只有一个,就是为了满足异常安全性。
    也可以看到,为了满足异常安全性,往往会损失一些效率,所以vector至今仍然只满足基本异常安全保证,我们的代码必须在某些时候作出一个选择,作出这个选择时,你的头脑必须是清醒的,你必须知道为什么这么做,有什么好处,有什么坏处,呵呵,要完全达到这个要求还需要长期的修炼