8.1.5  异常和效率

8.1.5 异常和效率

在没有抛出异常之前,异常处理的实现在运行时没有产生任何额外开销。抛出异常并不比调用函数的开销大。在完成这些的同时,要维持与C语言在调用序列、排错规范等方面的兼容性,而又不引起显著的额外存储开销,这是非常困难的。简单使用那些能代替异常的东西是需要代价的。在多数的大规模程序中或系统软件中,更多的代码(甚至超过一半)实际上是用于错误处理和异常处理的。对于下述形式的代码:

978-7-111-51399-5-Chapter08-21.jpg

如果g()函数会抛出异常,那么f()函数必须包含部分代码,使异常发生时能够得到即时处理。例如,确保字符串变量s被正确销毁。如果g()函数不采用抛出异常的方式,也会得到使用另一种方式报告发生的错误。与之相较,使用常规方式写出的处理错误的代码需要包含大量的if判断和return语句。就像排雷一样,走一步就要判断一步。

异常描述可能非常有助于改进所生成的代码。但是,传统的C函数不会抛出异常的。大部分程序中,每个C函数均可用“空抛出”描述throw()声明,即

978-7-111-51399-5-Chapter08-22.jpg

上述函数定义中throw()的参数表为空,说明此函数不能抛出任何异常。对于标准C库函数只有很少的几个函数可以抛出异常,例如atexit()和qsort()。

978-7-111-51399-5-Chapter08-23.jpg

atexit()函数指定func()函数在程序终止时被调用。如果调用成功,函数返回0;如果调用失败,函数返回非零。进程函数func()必须返回void,并且不允许包含参数。

qsort()函数在前面讲述算法的章节已有介绍。

利用这些函数可以生成更优质的代码。值得注意的是,在为某个C函数空异常描述throw()之前,要思考一下该函数是否有必要抛出异常。