1. 函数return值与try块throw exception、函数接收参数与catch字句捕获异常相当类似(不仅声明形式相像,函数参数与exception传递方式都有三种:by value,by reference ,by pointer(本质上也是by value) )。
2. 尽管函数调用与异常抛出相当类似,“从抛出端传递一个exception到catch子句”和“从函数调用端传递一个实参到被调函数参数”仍然大有不同:
1)调用一个函数,控制权会最终回到调用端(除非函数失败以致无法返回),但是抛出一个exception,控制权不会再回到抛出端
可以简单理解函数调用作用域是“外—里—外”的转换,而异常抛出是“里—外—···”的转换(只是便于理解,实际上这个比方并不正确)
2)如果函数调用的参数是按引用传递的,那么实参不会被复制,但无论catch接收的异常是按引用还是按值传递,被抛出的异常对象至少被复制一次,原因在于栈展开过程中局部对象都被销毁,因而需要产生一个临时对象保存被throw的异常,这与函数return时用一个临时对象来暂时保存return的对象是一样的(函数return存在NRV(有的也叫RVO)优化,可以省略调用拷贝构造函数)。也就是说,在第一个catch子句接受异常时,那个异常已经是被复制过一次的临时对象,如果catch子句的参数是按值传递,那么临时对象还需要再被复制一次。因此异常处理通常要付出较高的代价。
3)函数可以返回引用,catch子句不可能重新抛出一个引用,对于以下代码:
1 try{ 2 throw Derived; 3 } 4 catch(Base & tmp){ 5 throw tmp; 6 }