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

时间:2011-03-24 23:13:00

标签: c++ exception

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

11 个答案:

答案 0 :(得分:15)

观察偏见在这里工作。

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

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

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

答案 1 :(得分:10)

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

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

答案 2 :(得分: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 ++异常处理。 我永远不会考虑为这样的平台编写软件, 以同样的方式,我拒绝在汇编代码中编写复杂的应用程序。

答案 3 :(得分:6)

好奇。我经常使用C ++工作,至少有十年 自从我看到任何不使用异常的C ++代码以来。 任何时候你必须传播一个重要数字的错误 堆栈帧,你使用例外。

答案 4 :(得分:4)

我想到了几个原因:

  1. 异常不应该非常明显,因为它们被设计为深陷在库的内部并且在调用堆栈中的某个位置被捕获(甚至高达main())。
  2. 它们旨在发出异常(即罕见和意外)故障的信号。例如,打开文件失败并不是特别特别。因此,默认情况下,iostream库在打开文件失败时不会抛出异常。
  3. 抛出例外是非常昂贵的,这鼓励遵守设计意图。
  4. 抛出异常的C ++库无法与C程序轻松连接。

答案 5 :(得分:1)

我可以说同样的事情并且它不会有太大的偏见,如果我定义这对于Microsoft世界和RAD来说都是如此。

我认为这是因为今天你本身不使用C ++程序,而是使用C ++库的高级语言混合。通常你有一个托管非管理的边界。

通过这个边界投掷和捕捉异常就像在你屁股点燃鞭炮:) - [读内存泄漏或更糟]

此外,如果使用COM对象,则必须使用COM异常,因此标准C ++异常的使用必须驻留在通常很小的库中。在小型库中,您不需要使用异常。

答案 6 :(得分:1)

因为“真实世界”代码和“教科书”代码之间存在巨大差异。

我在一家“大型”软件公司工作,可以诚实地告诉你,你在生产中看到的东西几乎占了你在好书中读到的良好做法的0%。

以Scott Meyers的Effective C ++书为例。应该是每个软件工程师办公桌上的副本,从东海岸到西部。

答案 7 :(得分:1)

对于初学者来说,例外情况太先进了,所以这些并不总是在示例中显示,特别是在书本上。

答案 8 :(得分:0)

  

我想到了几个原因:

     
      
  1. 例外不应该是非常明显的,因为它们的目的是为了   被深深地扔在图书馆的内部,高高举起   在调用堆栈中(甚至与main()一样高。)
  2.   

我不知道你的意思是“异常不应该非常明显”。 但我同意捕获块应该是罕见的 - 它们通常是主要的。

  
      
  1. 它们旨在表示异常(即罕见和意外)   故障。例如,打开文件失败并不是特别严重   例外的。因此,默认情况下,iostream库不会抛出   无法打开文件时出现异常。
  2.   

iostream库不会抛出异常使它变得无法使用。 隐藏来自呼叫者的错误! 这就像C一样。

  
      
  1. 例外是非常昂贵的投掷,这鼓励坚持   设计意图。
  2.   

通常例外是系统调用失败。 由于写入文件或打开文件并不是很便宜, 人们不会关心例外是否昂贵。 还必须检查成功比使用C ++异常处理更昂贵。 通常,人们不会在代码的时间关键部分内创建try-catch块。

  
      
  1. 抛出异常的C ++库不容易与C接口   程序。
  2.   

什么是C?啊是的 - 我记得 - 我在1996年左右放弃了。还记得Turbo Pascal吗?

答案 9 :(得分:0)

我说的是Windows的桌面应用程序。在我的观察中(也是YMMV),开发的早期阶段可能直到初始版本。许多开发人员不会在早期就考虑异常。这就是为什么几乎没有代码处理异常处理的原因,但是如果您已经有2或3个版本,或者您的维护阶段,则由于各种部署环境通过客户的错误报告而考虑异常。

答案 10 :(得分:0)

示例中没有使用豁免,因为它很少成为您想要了解的许多问题的焦点。