C++中为什么要使用异常?

很多人也许知道C++中的异常机制,很多人也许不知道。很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它。

对于C语言,使用正常的if-else即是很好的选择,而在C++中,如果使用了面向对象的编程,最好还是使用Exception机制。这主要设计对象能否正确的析构的问题。

C中的出错跳转setjmplongjmp

C语言中常用的用于处理异常的方法。它不像abort或者assert或者exit那样直接退出,也不像goto语句仅仅局限在函数内部。
它是用于一种长跳转的方式。可以从一个函数跳到这个函数上层的调用函数中。
举个例子

  1. 函数 A 中调用了setjmp设置了一个跳转位,然后函数A调用了函数B。
  2. 函数 B 中调用了longjmp,那么会使得程序条到 函数 A中调用setjmp的位置继续执行。

这不是本文的重点。

使用setjmplongjmp最大的缺点是可能会跳过某些对象的构造或者析构。
还有,在C中使用goto可以跳过某些变量的定义,但是这不会出什么问题。可以试试下面的代码。注意,是C语言,你要是用C++的编译器来编译,应该是会报错的。

 1 #include <stdio.h>
2
3 int main(int argc,char** argv)
4 {
5 if(argc > 1){
6 goto nodef;
7 }
8 int a = 102;
9 nodef:
10 printf(" a = %d\n",a);
11 return 0;
12 }

C++中使用setjmplongjmp造成的不良后果

我们先看代码

无法正常析构对象的代码

 1 #include <iostream>
2 #include <csetjmp>
3
4 using std::cout;
5 using std::endl;
6
7 class Test{
8 public:
9 Test(){ cout<<"Test 构造"<<endl;}
10 ~Test(){cout<<"Test 析构"<<endl;}
11 };
12
13 jmp_buf jbuf; //用于setjmp保存当前相关信息
14
15 void calljmp()
16 {
17 Test t; //测试能够正确调用析构
18 cout<<"call longjmp(jbuf,3721)"<<endl;
19 longjmp(jbuf,3721);
20 }
21
22 int main()
23 {
24 int ret=0;
25 if( 0 == (ret=setjmp(jbuf))){
26 cout<<"call setjmp(jbuf) resuces"<<endl;
27 calljmp();
28 }
29 else{
30 cout<<"call setjmp(jbuf) failed ret = "<< ret <<endl;
31 }
32 }

编译执行看看

可以看到,对象构造了,但是没有正常的调用析构。

1 o@o-pc:~/code_/exception$ g++ setjmp.cpp -o setjmp
2 o@o-pc:~/code_/exception$ ./setjmp
3 call setjmp(jbuf) resuces
4 Test 构造
5 call longjmp(jbuf,3721)
6 call setjmp(jbuf) failed ret = 3721

C++中使用异常处理的情况

C++中使用异常机制的好处之一,就是能够正确的去析构对象。

使用了异常处理机制的代码

 1 #include <iostream>
2 #include <csetjmp>
3
4 using std::cout;
5 using std::endl;
6
7 class Test{
8 public:
9 Test(){ cout<<"Test 构造"<<endl;}
10 ~Test(){cout<<"Test 析构"<<endl;}
11 };
12
13 jmp_buf jbuf; //用于setjmp保存当前相关信息
14
15 void calljmp()
16 {
17 Test t; //测试能够正确调用析构
18 cout<<"call longjmp(jbuf,3721)"<<endl;
19 //longjmp(jbuf,3721);
20 throw 3721;
21 }
22
23 int main()
24 {
25 try{
26 cout<<"调用calljmp 尝试抛出异常"<<endl;
27 calljmp();
28 }catch(int t){
29 cout<<"捕获到异常值:"<<t<<endl;
30 }
31 /*
32 int ret=0;
33 if( 0 == (ret=setjmp(jbuf))){
34 cout<<"call setjmp(jbuf) resuces"<<endl;
35 calljmp();
36 }
37 else{
38 cout<<"call setjmp(jbuf) failed ret = "<< ret <<endl;
39 }
40 */
41 }

编译运行试试

可以看到这次正常调用了析构函数

o@o-pc:~/code_/exception$ g++ exception.cpp -o exception
o@o-pc:~/code_/exception$ ./exception
调用calljmp 尝试抛出异常
Test 构造
call longjmp(jbuf,3721)
Test 析构
捕获到异常值:3721

http://www.cnblogs.com/oloroso/p/4616502.html

C/C++相对论——C++中为什么要使用异常(跳转语句会造成对象没有被析构)的更多相关文章

  1. C/C++相对论——C++中为什么要使用异常?

    C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...

  2. js中页面刷新和页面跳转的方法总结

    .js中cookie的基本用法简介 2009-12-15 js中页面刷新和页面跳转的方法总结 文章分类:Web前端 关键字: javascript js中页面刷新和页面跳转的方法总结 1.histor ...

  3. javaWeb中servlet开发(4)——servlet跳转

    servlet跳转 1.跳转类型 客户端跳转:跳转后地址栏改变,无法传递request范围内属性,是在所有的操作都执行完毕之后才发生跳转的操作,跳转语法是,response.sendRedict() ...

  4. 页面打开 抛出w3wp.exe 中发生未处理异常

    页面打开 抛出w3wp.exe 中发生未处理异常

  5. 向Oracle中传入数组,批量执行SQL语句

    1.首先用PL/SQL创建package create or replace package excuteBatchOperate as type sqlStr_Array ) index by bi ...

  6. 遇到问题-----JS中设置window.location.href跳转无效(在a标签里或这form表单里)

    问题情况 JS中设置window.location.href跳转无效 代码如下: ? 1 2 3 4 5 6 7 8 <script type="text/javascript&quo ...

  7. mybatis 中的稍微复杂些的sql语句

    mybatis 中的稍微复杂些的sql语句: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...

  8. Spring 中jdbcTemplate 实现执行多条sql语句

    说一下Spring框架中使用jdbcTemplate实现多条sql语句的执行: 很多情况下我们需要处理一件事情的时候需要对多个表执行多个sql语句,比如淘宝下单时,我们确认付款时要对自己银行账户的表里 ...

  9. union 中可以存储的是不带构造函数的类对象

    union 中可以存储的是不带构造函数的类对象 否则不符合逻辑 为什么不符合逻辑?

随机推荐

  1. [转]redis-cluster研究和使用--待研究

    转自:http://hot66hot.iteye.com/blog/2050676 一:关于redis cluster 1:redis cluster的现状 reids-cluster计划在redis ...

  2. Android 定位地理坐标体系

    参考: 中国特色 火星坐标 iOS 火星坐标相关整理及解决方案汇总 百度地图坐标转换API 地球坐标系 (WGS-84) 到火星坐标系 (GCJ-02)百度坐标系 (BD-09) 的转换算法 火星坐标 ...

  3. Codeforces Round #209 (Div. 2) B. Permutation

    解题思路: 如果序列a是单调递增的,则序列为1,2,..... 2n,则将给出的式子化简得Σ(a2i - a2i-1) = n 如果序列a是单调递减的,则序列为2n,.........2, 1,则将给 ...

  4. NOI 题库 1792

    1792  迷宫 描述 一天Extense在森林里探险的时候不小心走入了一个迷宫,迷宫可以看成是由n * n的格点组成,每个格点只有2种状态,.和#,前者表示可以通行后者表示不能通行.同时当Exten ...

  5. URAL 1057. Amount of Degrees(数位DP)

    题目链接 我看错题了...都是泪啊,不存在3*4^2这种情况...系数必须为1... #include <cstdio> #include <cstring> #include ...

  6. 【bzoj2333】 [SCOI2011]棘手的操作 可并堆+lazy标记

    2016-05-31  21:45:41 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=2333 (学习了黄学长的代码 有如下操作: U x y ...

  7. FS_11C14温湿度传感器(二)

    作者:刘老师,华清远见嵌入式学院讲师. 在FS_11C14平台DHT11传感器程序: /******************************************************** ...

  8. 【JavaService】部署Java jar为Windows后台服务

    将Java jar文件部署为Windows后台服务有多种方法:Service Installer.Java service Wrapper.JavaService.exe等等.这里介绍下使用JavaS ...

  9. php关于金额比较引发的问题(转)

    做电子商务的时候一般会涉及到金额的比较,按正常的思路来看用><=这些个符号就可以了.可是要是到程序上来搞这个的话就出大事了.现在看下这段代码: $f = 0.07; var_dump($f ...

  10. About_AJAX

    Asynchronous JavaScript And XML (1)AJAX大多用于验证和分页: (2)首先要激活(对象): window.ActiveXObject(针对IE): window.X ...