为了在运行时处理惩罚异常,措施要记录大量的信息。无论执行到什么处所,措施都必需可以或许识别出假如在此处抛出异常的话,将要被释放哪一个工具;措施必需知道每一个进口点,以便从try块中退出;对付每一个try块,他们都必需跟踪与其相关的catch子句以及这些catch子句可以或许捕捉的异常范例。这种信息的记录不是没有价钱的。确保措施满意异通例格不需要运行时的较量(runtime comparisons),并且当异常被抛出时也不消特另外开销来释放相关的工具和匹配正确的catch字句。可是异常处理惩罚确是有价钱的,纵然你没有利用try,throw或catch要害字,你同样得支付一些价钱。
让我们先从你不利用任何异常处理惩罚特性也要支付的价钱谈起。你需要空间成立数据布局来跟踪工具是否被完全结构(constructed)(介入条款10),你也需要系统时间保持这些数据布局不绝更新。这些开销一般不是很大,可是当回收不支持异常的要领编译的措施一般比支持异常的措施运行速度更快所占空间也更小。
在理论上,你不能对此举办选择:C++编译器必需支持异常,也就是说,当你不消异常处理惩罚时你不能让编译器出产商消除这方面的开销,因为措施一般由多个独立生成的方针文件(object files)构成,只有一个方针文件不举办异常处理惩罚并不能代表其他方针文件不举办异常处理惩罚。并且纵然构成可执行文件的方针文件都不举办异常处理惩罚,那么尚有它们所毗连的措施库呢?假如措施的任何部门利用了异常,其它部门必需也支持异常。不然在运行时措施就不行能提供正确的异常处理惩罚。
不外这只是理论,实际上大部门支持异常的编译器出产商都答允你自由节制是否在生成的代码里包括进支持异常的内容。假如你知道你措施的任何部门都不利用try,throw或catch,而且你也知道所毗连的措施库也没有利用try,throw或catch,你就可以回收不支持异常处理惩罚的要领举办编译,这可以缩小措施的尺寸和提高速度,不然你就得为一个不需要的特性而支付价钱。跟着时间的推移,利用异处理惩罚的措施库开始变得普遍了,上面这种要领将逐渐不能利用,可是按照今朝的软件开拓环境来看,假如你已经抉择不利用任何的异常特性,那么回收不支持异常的要领编译措施是一本机能优化的公道要领。同样这对付想避开异常的措施库来说也是一本机能优化的好要领,这能担保异常不会从客户端措施通报进措施库里,不外同时这样做也会故障客户端措施重界说措施库中声明的虚拟函数,并不答允有在客户端界说的回调函数。
利用异常处理惩罚的第二个开销来自于try块,无论何时利用它,也就是无论何时你想可以或许捕捉异常,那你都得为此支付价钱。差异的编译器实现try块的要领差异,所以编译器与编译器间的开销也纷歧样。大致地预计,假如你利用try块,代码的尺寸将增加5%-10%而且运行速度也同比例减慢。这照旧假设措施没有抛出异常,我这里接头的只是在措施里利用try块的开销。为了淘汰开销,你应该制止利用无用的try块。
编译器为异通例格生成的代码与它们为try块生成的代码一样多,所以一个异通例格一般花掉与tyr块一样多的系统开销。什么?你说你认为异通例格只是一个规格罢了,你认为它们不会发生代码?那么好,此刻你应该对此有新的认识了。
此刻我们来到了问题的焦点部门,看看抛出异常的开销。事实上我们不消太体贴这个问题,因为异常是很少见的,这种事件的产生往往被描写为exceptional(异常的,稀有的)。80-20法则(拜见条款16)汇报我们这样的事件不会对整个措施的机能造成太大的影响。可是我知道你仍旧好奇地想知道假如抛出一个异常到底会有多大的开销,谜底是这大概会较量大。与一个正常的函数返回对比,通过抛出异常从函数里返回大概会慢三个数量级。这个开销很大。可是仅仅当你抛出异常时才会有这个开销,一般不会产生。可是假如你用异常暗示一个较量普遍的状况,譬喻完成对数据布局的遍历或竣事一个轮回,那你必需从头予以思量。
不外请等一下,你问我是怎么知道这些工作的呢?假如说支持异常对付大大都编译器来说是一个较新的特性,假如说差异的编译器异常要领也差异,那么我如何能说措施的尺寸将增大5%-10%,它的速度也同比例减慢,并且假如有大量的异常被抛出,措施运行速度会呈数量级的减慢呢?谜底是令人恐慌的:一些据说和一些基准测试(benchmarks)(拜见条款23)。事实是大部门人包罗编译器出产商在异常处理惩罚方面险些没有什么履历,所以尽量我们知道异常确实会带来开销,却很难预测出开销的精确数量。
#p#分页标题#e#
审慎的要领是对本条款所论述的开销有相识,可是不深究详细的数量。(即定性不定量 译者注)岂论异常处理惩罚的开销有多大我们都得僵持只有必需支付时才支付的原则。为了使你的异常开销最小化,只要大概只管就回收不支持异常的要领编译措施,把利用try块和异通例格限制在你确实需要它们的处所,而且只有在确为异常的环境下(exceptional)才抛出异常。假如你在机能上仍旧有问题,总体评估一下你的软件以抉择异常支持是否是一个起浸染的因素。假如是,那就思量选择其它的编译器,能在C++异常处理惩罚方面具有更高实现效率的编译器。