在C ++中使用try / catch块

时间:2009-06-04 15:44:42

标签: c++ exception-handling try-catch

一般情况下,我倾向于将try / catch用于具有多个故障点的代码,其中故障具有公共处理程序。

根据我的经验,这通常是在执行某些操作后执行某些操作或输出之前对输入或上下文进行限定的代码。

我收到了文献和同事的建议,以尽量减少这些块中的代码,我接受这一点作为一般的好建议。

我想更多地了解上述建议的基础:

  • 开销的性质是什么?
  • 是否有最新的开发指南解决了try / catch块的推荐用法(或避免)?
  • 更快的处理器和更现代的编译器可以缓解try / catch的问题吗?

提前感谢您的帮助,

AJ

8 个答案:

答案 0 :(得分:17)

在c ++中,成本取决于实现。通常,有两种方法可以实现异常:

首先是“表格”方法。编译器构建一组表来查找,抛出异常的位置,去哪里。抛出异常时,它必须在调用堆栈中搜索每个表,直到找到可以捕获此异常的内容。由于这都是基于运行时的,因此输入或退出try catch不会产生任何惩罚(好),但抛出异常可能会导致许多查找,从而产生更慢的抛出。我个人更喜欢尝试捕获块不需要付费,因为异常应该是非常罕见的情况。如果必须存储表,这也会使可执行文件更大。

秒是“代码”方法。每次代码进入try catch块时,概念上,块的位置被压入堆栈。这会在进入和退出try-catch块时产生成本,但是,当抛出异常时,运行时机制可以快速弹出堆栈以找到要去的地方。因此,抛出异常(更多?)更快,但现在进入一个区块需要付出代价。将try catch块置于紧密的低级循环中可能会产生很大的开销。

您必须检查您的特定编译器以查看它们使用的编译器。

答案 1 :(得分:6)

我发现了a technical report on C++ performance(pdf警告),其中包含有关例外的部分。你可能会发现它很有趣。我有同事认为try / catch块中的每条指令都有开销,但这份技术报告似乎并不支持这个想法。

答案 2 :(得分:5)

关于第二个问题:一般准则是here, Herb Sutter也给出了很好的建议here

答案 3 :(得分:2)

取决于编译器。为什么不使用try-catch块编写一个简单的函数,而没有它的类似函数并比较生成的机器代码?

答案 4 :(得分:1)

我发现C ++常见问题解答网站和相应的书籍对此事有一个启发性的讨论。

http://www.parashift.com/c++-faq-lite/exceptions.html

答案 5 :(得分:0)

根据我的经验,try / catch块的最大问题是我们经常尝试过于普遍地捕获异常。例如,如果我用一个捕获(...)的try / catch块包装我的main函数,我基本上试图不允许我的程序崩溃抛出异常的b / c。

我认为这种方法的问题有两个方面。 1)当我测试和调试时,我没有看到任何错误,我没有机会修复它们。 2)这是一种慵懒的出路。而不是考虑可能出现的问题并弄清楚边缘情况是什么,我只是试着不要失败。尽量不要失败与尝试成功有很大不同。

答案 6 :(得分:0)

在大多数语言中,通过常规方法进入和退出try / catch块是免费的,只有在抛出异常时,异常处理程序才会查找处理异常的位置。

答案 7 :(得分:0)

在C ++中,您不应该使用try / catch块来执行清理。相反,您可能希望使用模板来执行资源获取。

auto_ptr是一个[坏]示例

同步锁定,其中将互斥锁存储为状态变量,并使用局部变量(模板或常规类)来执行.acquire()/。release()方法。

您执行的操作越多,您就越不必担心在特殊情况下手动释放对象。 C ++编译器将为您完成。