C++为什么抓不到除0错“异常”?

来源:互联网 发布:c语言不等于 编辑:程序博客网 时间:2024/04/29 12:34


http://blog.csdn.net/nanyu/article/details/6475555

有人问这个问题:

Code:
  1. try  
  2. {  
  3.      std::cout << 10/0 << std::endl;  
  4. }  
  5. catch(...)  
  6. {  
  7.      std::cout << "exception" << std::endl;  
  8. }  

这段代码,永远不会有机会在屏幕上输出 exception。

为什么? 因为和ada或java不一样,C++标准没有把除0错当成标准异常。

上面的代码原样放到VC里,我猜测(基于对VC的基本信任,也基于我的懒惰),VC也不会执行07行代码。VC里要抓这样的异常,需要采用操作系统的结构化异常。它的代码需要使用 __try/__except来处理。或者需要在编译选项上,加上让C++异常支持SEH(结构化异常处理)的参数。

C++之父在谈C++语言设计的书(The Design and Evolution of C++)里谈到:

 "low-level events, such as arithmetic overflows and divide by zero, are assumed to be handled by a dedicated lower-level mechanism rather than by exceptions. This enables C++ to match the behaviour of other languages when it comes to arithmetic. It also avoids the problems that occur on heavily pipelined architectures where events such as divide by zero are asynchronous."

简单翻译一下: “底层的事件,比如计算上的溢出和除0错,被认为应用有一个同样底层的机制去处理它们,而不是异常。这让C++在涉及到算术领域的性能,可以和其它语言竞争。再者,它也避免了当某些事件,比如除0错是异步的情况下(译者注:比如在别一个线程里发生)所可能造成的‘管道重重’的架构这一问题。”

所以,说起来,和原生数组访问越界为什么不是一异常并无两样,主要还是为了“效率/性能”。对于大多数时候的除法操作,我们会让它出现除数为0的可能性很小,当你认为有这种可能,就自己检查吧,然后自己定义一个除0错的异常。

很多C++库,还是实现了EDivByZero之类异常,但仅限于这个库里的代码。它们做了检查。

 总结一下:C++为什么抓不到除0错的“异常”? 答:因为C++标准眼里,除0错不是一个异常。再进一步:C++编译器,在编译除法操作时,没有为它加上额外的检查代码以抛出一个异常;也没有要求处理不同OS之间对(已经发生的)除0错的处理。

另一个原因是,简单化,比如如果要判断除0错,浮点数如何判断呢?

说到底,在事情发生之前,判断一下不是更好?

Code:
  1. if (b == 0)  
  2. {  
  3.     cout << "别玩我啦...拿个0当除数?" << std::endl;  
  4.     return -1;  
  5. }  

这样不是很好?

0 0