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

有人问这个问题:

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. }  

这样不是很好?

 

------------欢迎关注《白话 C++》的出版-------------------------

如果您想与我交流,请点击如下链接成为我的好友:
http://student.csdn.net/invite.php?u=112600&c=f635b3cf130f350c

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 14
    评论
C++ 中,assert 是一种宏定义,其目的是在代码中判断所给定的条件是否为真,如果为假,则终止程序的执行。如果想要将 assert 的行为修改为抛出异常,可以使用以下两种方法: 1.使用自定义宏定义 可以使用自定义宏定义来将 assert 的行为修改为抛出异常。下面是一个示例代码: ```c++ #include <stdexcept> #include <iostream> // 将 assert 的行为改为抛出 runtime_error 异常 #define assert(expression) \ if (!(expression)) \ throw std::runtime_error("Assertion failed: " #expression); int main() { int x = 10; int y = 5; assert(x > y); std::cout << "x > y" << std::endl; return 0; } ``` 在上面的代码中,我们使用了自定义宏定义将 assert 的行为修改为抛出 runtime_error 异常。在执行 assert(x > y) 的时候,如果 x > y 不成立,将会抛出一个 runtime_error 异常,程序的执行也会随之终止。 2.使用断言包装函数 另一种将 assert 的行为修改为抛出异常的方法是使用一个断言包装函数,这个函数将会接受一个表达式作为参数,如果表达式不成立,则将会抛出一个异常。下面是一个示例代码: ```c++ #include <stdexcept> #include <iostream> void assert_impl(bool expression, const char* message) { if (!expression) { throw std::runtime_error(message); } } #define assert(expression) assert_impl(expression, "Assertion failed: " #expression) int main() { int x = 10; int y = 5; assert(x > y); std::cout << "x > y" << std::endl; return 0; } ``` 在上面的代码中,我们定义了一个断言包装函数 assert_impl,这个函数将会接受一个表达式和一个消息作为参数,如果表达式不成立,则将会抛出一个带有消息的 runtime_error 异常。然后,我们重新定义了 assert 宏,将它替换为调用 assert_impl 函数。这样,在执行 assert(x > y) 的时候,如果 x > y 不成立,将会抛出一个带有消息的 runtime_error 异常,程序的执行也会随之终止。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 14
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

南郁

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值