More Effective(三)异常

本文深入探讨了C++中异常处理机制如何确保资源在对象生命周期内的合理管理,通过利用智能指针、constructors和destructors避免资源泄漏,并阐述了如何在try/catch语句块中阻止异常流出destructors之外,同时解释了抛出exception与传递参数或调用虚函数的区别,以及以byreference方式捕捉exception的优势。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

零 导论:

(1)异常特点:

*不能被忽略,忽略就会自动调用terminate函数,终止程序。

*产生异常后的stack处理过程(栈展开)能够确保局部对象的destructors被调用。


一 利用destructors避免泄漏资源:

*利用智能指针(如:auto_ptr)把资源封装在对象内(RAII),通常便可以在exceptions出现时避免泄漏资源。


二 在constructors内阻止资源泄漏:

(1)C++只会析构已构造完成的对象,对象只有在constructor构造完成才算是完全构建妥当。

(2)成员初始化列表只接受表达式。

(3)阻止方法:

*通常只需将所有可能的exceptions捕捉起来,执行某种清理工作,然后再重新抛出异常,使它传播出去。

*较好做法:将资源交给对象来管理,即智能指针。


三 禁止异常流出destructors之外:

(1)调用destructors的两种情况:

*对象正常状态下被销毁,即当它离开了它的生存空间或是被明确地删除。

*对象被exception处理机制销毁,即exception传播过程中的stack-unwinding(栈展开机制)。

(2)如果控制权因exception的因素离开destructor,而此时正有另一个exception处于作用状态,C++会调用terminate函数终止程序。

(3)阻止exception传出destructors之外的理由:

*避免terminate函数在exception传播过程的栈展开机制中被调用。

*协助确保destructors完成其应该完成的事情。

(4)阻止异常流出destructors的方法:try/catch语句块。


四 了解"抛出一个exception"与"传递一个参数"或"调用一个虚函数"之间的差异:

(1)函数参数和exception的传递方式有3种:by-value,by-reference,by-pointer。

(2)无论被捕捉的exception是什么传递方式,一个对象被抛出作为exception时,总会发生复制(在throw obj时)。

(3)主要差异:

*exceptions的对象总是被复制,如果以by value方式捕捉,它被复制两次。传递给函数参数的对象根据传递方式不一定被复制。

*抛出exception的对象的类型转换动作少(只有两种):继承框架中的类转换(基类的catch子句可以处理derived);从有型指针到void*指针的转换。

*catch子句以其“源代码出现顺序”被编译器检验比对,其中第一个匹配成功变执行。


五 以by reference 方式捕捉exception:

(1)by pointer方式的问题:

*需确保exception对象在抛出指针后依然存在(static)。

*抛出指针指向heap object时,应该避免资源泄漏。

*c++标准的exceptions都是对象,而不是对象指针。

(2)by value方式的问题:

*当exception objects被抛出时复制两次。

*会引起切割问题(slicing)。

(3)by reference方式:最佳,避免了资源泄漏问题,和标准异常类兼容,被复制一次,且没有切割问题。


六 明智运用exception specifications(异常说明):

(1)异常说明功能:

*明确指出一个函数可以抛出什么样的exceptions。

*如果函数抛出一个未列于异常说明的异常,这个错误会在运行期检查出来,于是unexpected函数会被自动调用。unexpected函数默认调用terminate函数。

(2)编译器只对异常说明做局部性检验,没有检验:调用某个函数可能会违反调用端本身的异常说明。

(3)使用异常说明的技巧:

*避免将异常说明放在“需要类型自变量”的templates上,因为没有方法知道一个template参数会抛出说明异常。

*如果A函数调用函数B,而B没有异常说明,那么A本身也不要设定异常说明。

*处理“系统”抛出的异常。

(4)C++允许以不同类型的exception取代非预期的exception。

*set_unexpected(函数名字):取代默认的unexpected函数。

*原理:如果非预期函数的替代者重新抛出当前对象,该exception会被标准类型bad_exception取而代之。

*上述操作后,让每一个异常说明都含有bad_exception,就不必担心程序遇上非预期的exception时终止执行。

(5)异常说明是一把双刃剑,加入函数之前,请考虑它所带来的程序行为是否真是你想要的。


七 了解异常处理的成本。








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值