More effective C++:审慎使用异常规格

毫无疑问,异常规格是一个引人注目的特性。它使得代码更容易理解,因为它明确地描述了一个函数可以抛出什么样的异常。但是它不只是一个有趣的注释。编译器在编译时有时能够检测到异常规格的不一致。而且如果一个函数抛出一个不在异常规格范围里的异常,系统在运行时能够检测出这个错误,然后一个特殊函数unexpected将被自动地调用。异常规格既可以做为一个指导性文档同时也是异常使用的强制约束机制,它好像有着很诱人的外表。

不过在通常情况下,美貌只是一层皮,外表的美丽并不代表其内在的素质。函数unexpected缺省的行为是调用函数terminate,而terminate缺省的行为是调用函数abort,所以一个违反异常规格的程序其缺省的行为就是halt(停止运行)。在激活的stack frame中的局部变量没有被释放,因为abort在关闭程序时不进行这样的清除操作。对异常规格的触犯变成了一场并不应该发生的灾难。

不幸的是,我们很容易就能够编写出导致发生这种灾难的函数。编译器仅仅部分地检测异常的使用是否与异常规格保持一致。一个函数调用了另一个函数,并且后者可能抛出一个违反前者异常规格的异常,(A函数调用B函数,因为B函数可能抛出一个不在A函数异常规格之内的异常,所以这个函数调用就违反了A函数的异常规格 译者注)编译器不对此种情况进行检测,并且语言标准也禁止它们拒绝这种调用方式(尽管可以显示警告信息)。

例如函数f1没有声明异常规格,这样的函数就可以抛出任意种类的异常:

extern void f1(); // 可以抛出任意的异常

假设有一个函数f2通过它的异常规格来声明其只能抛出int类型的异常:

void f2() throw(int);

f2调用f1是非常合法的,即使f1可能抛出一个违反f2异常规格的异常:

时间: 2024-09-08 23:27:06

More effective C++:审慎使用异常规格的相关文章

C++中审慎使用异常规格

毫无疑问,异常规格是一个引人注目的特性.它使得代码更容易理解,因为它明确地描述了一个函数可以抛出什么样的异常.但是它不只是一个有趣的注释.编译器在编译时有时能够检测到异常规格的不一致.而且如果一个函数抛出一个不在异常规格范围里的异常,系统在运行时能够检测出这个错误,然后一个特殊函数unexpected将被自动地调用.异常规格既可以做为一个指导性文档同时也是异常使用的强制约束机制,它好像有着很诱人的外表. 不过在通常情况下,美貌只是一层皮,外表的美丽并不代表其内在的素质.函数unexpected缺

大家在做项目的时候对异常是怎么处理的

问题描述 1.原样抛出还是不抛出?2.原样抛出还是转化为自定义的异常?3.如果有多个异常是放到一个try...catch块里面还是放在多个?4.如果有异常,例如:SQLException是抛出SQLException还是抛出Exception?5.怎样抛出异常才是更合理的呢? 解决方案 第一条,抛还是不抛,取决于你现在处理还是暂时不处理.无论如何,出了异常掩盖掉总是不合适的吧 =,.=第二条,取决于你的异常的用途,说实话,自定义exception,对于非web软件,工具类(比如框架之类),用的更

C++的可移植性和跨平台开发[3]:异常处理

上一个帖子"语法"由于篇幅有限,没来得及聊异常,现在把和异常相关的部 分单独拿出来说一下. ★小心new分配内存失败 早期的老式编译器生成的代码,如果new失败会返回空指针.我当年用的Borland C++ 3.1 似乎就是这样的,现在这种编译器应该不多见了.如果你目前用的编译器还有这种行为,那 你就惨了.你可以考虑重载new操作符来抛出bad_alloc异常,便于进行异常处理. 稍微新式一点的编译器,就不是仅仅返回空指针了.当new操作符发现内存告急,按照标 准的规定(参见03标准1

了解C++异常处理的系统开支

为了在运行时处理异常,程序要记录大量的信息.无论执行到什么地方,程序都必须能够识别出如果在此处抛出异常的话,将要被释放哪一个对象;程序必须知道每一个入口点,以便从try块中退出;对于每一个try块,他们都必须跟踪与其相关的catch子句以及这些catch子句能够捕获的异常类型.这种信息的记录不是没有代价的.确保程序满足异常规格不需要运行时的比较(runtime comparisons),而且当异常被抛出时也不用额外的开销来释放相关的对象和匹配正确的catch字句.但是异常处理确是有代价的,即使你

Java面试笔试题大汇总(最全+详细答案)

声明:有人说, 有些面试题很变态,个人认为其实是因为我们基础不扎实或者没有深入.本篇文章来自一位很资深的前辈对于最近java面试题目所做的总结归纳,有170道题目 ,知识面很广 ,而且这位前辈对于每个题都自己测试给出了答案 ,如果你对某个题有疑问或者不明白,可以电脑端登录把题目复制下来然后发表评论,大家一起探讨,也可以电脑端登录后关注我给我发私信,我们一起进步! 以下内容来自这位前辈 2013年年底的时候,我看到了网上流传的一个叫做<Java面试题大全>的东西,认真的阅读了以后发现里面的很多题

《C++编程剖析:问题、方案和设计准则》——第一章泛型编程与C++标准库1.1:vector的使用

第一章泛型编程与C++标准库 C++编程剖析:问题.方案和设计准则C++最强大的特性之一就是对泛型编程的支持.C++标准库的高度灵活性就是明证,尤其是标准库中的容器.迭代器以及算法部分(最初也称为STL). 与我的另一本书More Exceptional C++ [Sutter02]一样,本书的开头几条也是介绍STL中一些我们平常熟悉的部件,如vector和string,另外也介绍了一些不那么常见的设施.例如,在使用最基本的容器vector时如何避免常见的陷阱?如何在C++中进行常见的C风格字符

More Effective C++ 读书笔记五——异常

条款12:了解"抛出一个exception"与"传递一个参数"或"调用一个虚函数"之间的差异 第一,exception object总是会被复制,如果以by value方式捕捉,它们甚至被复制两次.至于传递给函数参数的对象不一定得复制.第二,"被抛出成为exceptions"的对象,其被允许的类型转换动作,比"被传递到函数去"的对象少.第三,catch子句以其"出现于源代码的顺序"被编译

《Effective C++》读书笔记08:别让异常逃离析构函数

这节和异常有关,这一块是我不太熟悉的,只能先把自己理解的记录下来. 1 class Widget 2 { 3 public: 4 5 ~Widget() {} //假设这里会吐出一个异常 6 }; 7 8 void doSomething() 9 { 10 std::vector<Widget> v; 11 12 }//v在这里自动销毁 上面的代码中,假设v含有10个Widget,如果在前面几个的析构函数中弹出异常,则程 序会过早结束或者出现不明确行为. 确实不鼓励在析构函数中抛出异常,可是如

Effective C#原则45:选择强异常来保护程序

当你抛出异常时,你就在应用程序中引入了一个中断事件.而且危机到程序 的控制流程.使得期望的行为不能发生.更糟糕的是,你还要把清理工作留给最 终写代码捕获了异常的程序员.而当一个异常发生时,如果你可以从你所管理的 程序状态中直接捕获,那么你还可以采取一些有效的方法.谢天谢地,C#社区不 须要创建自己的异常安全策略,C++社区里的人已经为我们完成了所有的艰巨的 工作.以Tom Cargill的文章开头:"异常处理:一种错误的安全感觉, " 而且Herb Sutter,Scott Meyer