为什么在C++中很少使用异常

6 c++ exception

我已经用C++编程开启和关闭了大约5年,为什么我从未见过除例子以外的例外用例?

Ben*_*igt 15

观察偏见在这里工作.

C++代码的很大一部分用于系统编程和嵌入式系统.(毕竟,C++只是应用程序编程的众多选项之一,而且许多替代方案都具有更高级的RAD环境,但在系统工作中,它通常是编译器可用的最高级语言,大幅度提高).大多数嵌入式系统以及大量系统开发工作都有限制条件来排除异常.

如果由于您的关注,您倾向于搜索这种代码,那么您看到的C++代码完全有可能不会使用异常.

这并不意味着没有使用异常的C++代码 - 有很多,有很多.它可能不会出现在旨在解决感兴趣的问题的代码中.


Pét*_*rök 10

异常是对语言的一个相当晚的补充,所以我相信许多C++开发人员从未学会正确使用它们,并且使用传统(C风格)错误处理技术可能会感到更放松.

我个人认为它们在处理构造函数失败方面是不可或缺的(这是它们最终被添加到C++中的最重要原因),但它们还需要正确使用其他高级(YMMV)技术(如RAII或智能指针)以避免资源泄漏.

  • 很少有图书馆使用它们 - 因为没有人使用它们 - 因为很少有图书馆使用它们.... (8认同)
  • 构造函数是一个很好的构造函数,但运算符是异常非常有用的另一种情况:通常没有简单,直接的方法来返回错误代码并知道用户不会忽略它. (4认同)

小智 7

我已经用C++编程开启和关闭了大约5年,为什么我从未见过除例子以外的例外用例?

我对此非常好奇.自1996年以来,我对此非常好奇.有时我认为在1996年,C++ Exception Handling彻底改变了我编写软件的方式.我记得我正在阅读有关C++异常处理的内容,我立即明白其含义.几分钟之内,我正在测试发生了什么,如果从构造函数抛出异常.用于UNIX的编译器还没有为C++异常处理做好准备,直到G ++ 3.0我认为(这是什么?).调用析构函数是为了没有构造的内存位置(在堆栈上)(如果抛出了一些异常).没有为成功的构造对象(在堆栈上)调用析构函数(如果抛出了某些异常).如果使用new创建的对象从构造函数中引发异常,则不会调用delete.适用于Windows和OS/2的编译器已于1996/1997准备就绪.他们工作.我记得Borland C++ for OS/2和IBM CSet2以及Windows Visual C++.

最后有一种方法可以中止对象的构造.最后,可以在构造函数中分配一个对象,并依赖于在其他构造函数中成功构造此对象.不知怎的,我发现了所有的规则.不是来自书本!多年后出版了书籍,声称C++异常处理是一种很好的方法来捕获数组越界错误或其他我从未停止使用断言的问题.最后,有一种简单的方法可以为调用者提供有关某些错误的复杂信息,而无需依赖stderr.最后,人们不需要调试一些复杂的软件来找出失败的东西.

我不能认真对待那些没有使用C++异常处理的人.无法检查每一个错误的电话.如果不使用C++异常处理,就不可能达到相同的软件质量水平.为什么这样的人仍然被雇用?为什么还有平台,它们不提供C++异常处理.我永远不会考虑为这样的平台编写软件,就像我拒绝在汇编代码中编写复杂的应用程序一样.


Jam*_*nze 6

好奇.我经常使用C++工作,自从我看到任何不使用异常的C++代码以来,已经至少十年了.每当您必须在大量堆栈帧中传播错误时,您都会使用异常.


Mar*_*tos 5

我想到了几个原因:

  1. 异常不应该非常明显,因为它们被设计为被扔进库的深处并在调用堆栈的高处捕获(甚至高达main())。
  2. 它们旨在表示异常(即罕见和意外)故障。例如,无法打开文件并不是特别例外。因此,默认情况下,iostream 库在打开文件失败时不会抛出异常。
  3. 抛出异常的成本非常高,这鼓励遵守设计意图。
  4. 抛出异常的 C++ 库不能轻松地与 C 程序交互。

  • “抛出异常的成本非常高”——有多贵?我想上次我尝试对此进行分析时,我得到了跨多个堆栈级别每次抛出/捕获大约 10us 的数字,因为使用“return”退出调用堆栈的额外成本。抛开实时系统不谈,如果每秒发生足够多的“罕见和意外”故障,可以检测到这种开销,那么您的程序有比性能更重要的问题需要修复;-) (7认同)
  • @Marcelo - 我们将很少发生的 10us 与总是发生的“几个”ns 进行比较。我们如何才能预先知道什么是最贵的?不必总是检查返回代码,可能会使您的热路径更快。 (7认同)
  • @Steve Jessop:有趣的是,如果在 macbook pro(Core 2 Duo 2.53GHz)上使用“g++ -O3”编译,然后计时几次,则在“return”情况下显示“0.002”秒的高度一致性在“throw”版本中,“0.416”秒。当您评论说异常的成本并没有更高时,我感到很惊讶,因为在我们看到它们的影响后,我们在工作中禁止它们进入我们的内部循环......然后再说一次,在核心之外,系统确实使用异常。 (2认同)
  • @Steve:猜猜你的优化器不好,或者你正在使用一个不够大的玩具项目进行测试。一种众所周知的优化是将异常处理程序与快速路径代码分开,以提高代码局部性,从而提高 i-cache 命中率。作为奖励,工作集更小。通过这种优化,当操作系统加载相关代码时,抛出异常可能会导致页面错误。但对于玩具基准测试来说,热代码和冷代码可能都适合在一个页面中。现在你正在谈论几毫秒的异常处理成本。 (2认同)