3 回答
TA贡献1876条经验 获得超5个赞
当今用于例外(Itanium ABI,VC ++ 64位)的主要模型是零成本模型例外。
这样做的想法是,编译器将生成一个边表,该边表将可能引发异常的任何点(程序计数器)映射到处理程序列表,而不是通过设置防护程序并在所有地方明确检查是否存在异常来浪费时间。引发异常时,将查询此列表以选择正确的处理程序(如果有),并取消堆栈堆栈。
与典型if (error)策略相比:
顾名思义,零成本模型在没有异常发生时是免费的
if发生异常时,费用约为10倍/ 20倍
然而,成本并不是微不足道的:
边桌通常很冷,因此从内存中获取它要花费很长时间
确定正确的处理程序涉及到RTTI:要提取的许多RTTI描述符,分散在内存中以及要运行的复杂操作(基本上是dynamic_cast对每个处理程序的测试)
因此,大多数缓存未命中,因此与纯CPU代码相比并不容易。
注意:有关更多详细信息,请阅读TR18015报告的第5.4节异常处理(pdf)
因此,是的,异常路径在异常路径上速度较慢,但与其他方式相比,它们通常比显式检查(if策略)更快。
注意:安德烈·亚历山德列斯库(Andrei Alexandrescu)似乎质疑这种“快速”。我个人已经看到事情发生了双向变化,有些程序在例外情况下运行得更快,而在分支程序中运行得更快,因此在某些情况下确实确实缺乏优化性。
有关系吗 ?
我会声称没有。编写程序时应考虑可读性,而不要考虑性能(至少,不作为首要标准)。当人们期望调用者无法或不希望当场处理失败并将失败传递到堆栈时,将使用异常。奖励:在C ++ 11中,可以使用标准库在线程之间封送异常。
不过,这很微妙,我声称map::find不应抛出,但是如果尝试取消引用失败,因为它为null,那么我可以map::find返回一个checked_ptrwhich抛出异常:在后一种情况下,就像Alexandrescu引入的类一样,调用者选择在显式检查和依赖异常之间。在不给呼叫者更多责任的情况下授权呼叫者通常是良好设计的标志。
TA贡献2019条经验 获得超9个赞
这取决于编译器。
例如,GCC以处理异常时的性能很差而著称,但是在过去几年中,这种情况变得更好了。
但是请注意,处理异常(顾名思义)应该是异常,而不是软件设计中的规则。当您的应用程序每秒抛出如此多的异常以至于影响性能并且仍然被认为是正常操作时,您应该宁愿以不同的方式去做。
异常是通过消除所有笨拙的错误处理代码来提高代码可读性的好方法,但是一旦它们成为常规程序流程的一部分,它们就会变得很难遵循。请记住,a throw
几乎是goto catch
伪装的。
- 3 回答
- 0 关注
- 611 浏览
添加回答
举报