C++ - 为什么析构函数不允许抛出异常
2011-04-06 19:23
309 查看
C++异常处理模型是为C++语言量身设计的,更进一步的说,它实际上也是为C++语言中面向对象而服务的,C++异常处理模型最大的特点和优势就是对C++中的面向对象提供了最强大的无缝支持。好的,既然如此!那么如果对象在运行期间出现了异常,C++异
常处理模型有责任清除那些由于出现异常所导致的已经失效了的对象(也即对象超出了它原来的作用域),并释放对象原来所分配的
资源,
这就是调用这些对象的析构函数来完成释放资源的任务,所以从这个意义上说,析构函数已经变成了异常处理的一部分。不知大家是否明白了这段话所蕴含的真正内
在涵义没有,那就是上面的论述C++异常处理模型它其实是有一个前提假设——析构函数中是不应该再有异常抛出的。试想!如果对象出了异常,现在异常处理模
块为了维护系统对象数据的一致性,避免资源泄漏,有责任释放这个对象的资源,调用对象的析构函数,可现在假如析构过程又再出现异常,那么请问由谁来保证这
个对象的资源释放呢?而且这新出现的异常又由谁来处理呢?不要忘记前面的一个异常目前都还没有处理结束,因此这就陷入了一个矛盾之中,或者说无限的递归嵌
套之中。所以C++标准就做出了这种假设,当然这种假设也是完全合理的,在对象的构造过程中,或许由于系统资源有限而致使对象需要的资源无法得到满足,从
而导致异常的出现,但析构函数完全是可以做得到避免异常的发生,毕竟你是在释放资源呀!
假如无法保证在析构函数中不发生异常,怎么办? 虽然C++标准中假定了析构函数中不应该,也不永许抛出异常的。但有过的实际的软件开发的程序员朋友们中也许会体会到,C++标准中的这种假定
完全是站着讲话不觉得腰痛,实际的软件系统开发中是很难保证到这一点的。所有的析构函数的执行过程完全不发生一点异常,这根本就是天方夜谭,或者说自己欺
骗自己算了。而且大家是否还有过这种体会,有时候发现析构一个对象(释放资源)比构造一个对象还更容易发生异常,例如一个表示引用记数的句柄不小心出错,
结果导致资源重复释放而发生异常,当然这种错误大多时候是由于程序员所设计的算法在逻辑上有些小问题所导致的,但不要忘记现在的系统非常复杂,不可能保证
所有的程序员写出的程序完全没有bug。因此杜绝在析构函数中决不发生任何异常的这种保证确实是有点理想化了。
那么当无法保证在析构函数中不发生异常时,
该怎么办?我们不能眼睁睁地看着系统崩溃呀!
其实还是有很好办法来解决的。那就是把异常完全封装在析构函数内部,决不让异常抛出函数之外。这是一种非常简单,也非常有效的方法。
析构函数抛出异常,C++将调用terminate函数。这个函数的作用正如其名字所表示的:它终止你程序的运行,而且是立即终止,甚至连局部对象都没有被释放。那个时候,也许你的系统有时就会莫名奇妙地崩溃而退出了,而且什么迹象也没有,崩得你满地找牙也很难发现问题究竟出现在什么地方
常处理模型有责任清除那些由于出现异常所导致的已经失效了的对象(也即对象超出了它原来的作用域),并释放对象原来所分配的
资源,
这就是调用这些对象的析构函数来完成释放资源的任务,所以从这个意义上说,析构函数已经变成了异常处理的一部分。不知大家是否明白了这段话所蕴含的真正内
在涵义没有,那就是上面的论述C++异常处理模型它其实是有一个前提假设——析构函数中是不应该再有异常抛出的。试想!如果对象出了异常,现在异常处理模
块为了维护系统对象数据的一致性,避免资源泄漏,有责任释放这个对象的资源,调用对象的析构函数,可现在假如析构过程又再出现异常,那么请问由谁来保证这
个对象的资源释放呢?而且这新出现的异常又由谁来处理呢?不要忘记前面的一个异常目前都还没有处理结束,因此这就陷入了一个矛盾之中,或者说无限的递归嵌
套之中。所以C++标准就做出了这种假设,当然这种假设也是完全合理的,在对象的构造过程中,或许由于系统资源有限而致使对象需要的资源无法得到满足,从
而导致异常的出现,但析构函数完全是可以做得到避免异常的发生,毕竟你是在释放资源呀!
假如无法保证在析构函数中不发生异常,怎么办? 虽然C++标准中假定了析构函数中不应该,也不永许抛出异常的。但有过的实际的软件开发的程序员朋友们中也许会体会到,C++标准中的这种假定
完全是站着讲话不觉得腰痛,实际的软件系统开发中是很难保证到这一点的。所有的析构函数的执行过程完全不发生一点异常,这根本就是天方夜谭,或者说自己欺
骗自己算了。而且大家是否还有过这种体会,有时候发现析构一个对象(释放资源)比构造一个对象还更容易发生异常,例如一个表示引用记数的句柄不小心出错,
结果导致资源重复释放而发生异常,当然这种错误大多时候是由于程序员所设计的算法在逻辑上有些小问题所导致的,但不要忘记现在的系统非常复杂,不可能保证
所有的程序员写出的程序完全没有bug。因此杜绝在析构函数中决不发生任何异常的这种保证确实是有点理想化了。
那么当无法保证在析构函数中不发生异常时,
该怎么办?我们不能眼睁睁地看着系统崩溃呀!
其实还是有很好办法来解决的。那就是把异常完全封装在析构函数内部,决不让异常抛出函数之外。这是一种非常简单,也非常有效的方法。
析构函数抛出异常,C++将调用terminate函数。这个函数的作用正如其名字所表示的:它终止你程序的运行,而且是立即终止,甚至连局部对象都没有被释放。那个时候,也许你的系统有时就会莫名奇妙地崩溃而退出了,而且什么迹象也没有,崩得你满地找牙也很难发现问题究竟出现在什么地方
相关文章推荐
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 为什么析构函数不能抛出异常问题
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 为什么析构函数不能抛出异常
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- C++ 异常 与 ”为什么析构函数不能抛出异常“ 问题
- 【中级】C++析构函数抛出异常
- c++能否在析构函数和构造函数中抛出异常?
- 构造函数、析构函数可以抛出异常吗?为什么?(一道百度面试题)
- [c/c++]构造函数、析构函数中可不可以抛出异常
- 【effective c++】C++构造函数、析构函数与抛出异常
- 为什么在析构函数中不应该抛出异常?
- C++之构造函数、析构函数抛出异常的问题
- C++关于构造函数 和 析构函数 能否抛出异常的讨论
- C++ 析构函数中抛出的异常
- C++中构造函数和析构函数可以抛出异常吗?
- 为什么虚构函数不允许抛出异常