C++中为什么要使用异常?
很多人也许知道C++中的异常机制,很多人也许不知道。很多人知道C中常用的assert
,也知道在编译时候指定NODEBUG
来忽略它。
对于C语言,使用正常的if-else
即是很好的选择,而在C++中,如果使用了面向对象的编程,最好还是使用Exception
机制。这主要设计对象能否正确的析构的问题。
C中的出错跳转setjmp
和longjmp
C语言中常用的用于处理异常的方法。它不像abort
或者assert
或者exit
那样直接退出,也不像goto
语句仅仅局限在函数内部。
它是用于一种长跳转的方式。可以从一个函数跳到这个函数上层的调用函数中。
举个例子
- 函数 A 中调用了
setjmp
设置了一个跳转位,然后函数A调用了函数B。 - 函数 B 中调用了
longjmp
,那么会使得程序条到 函数 A中调用setjmp
的位置继续执行。
这不是本文的重点。
使用setjmp
和longjmp
最大的缺点是可能会跳过某些对象的构造或者析构。
还有,在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++中使用setjmp
和longjmp
造成的不良后果
我们先看代码
无法正常析构对象的代码
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++中为什么要使用异常(跳转语句会造成对象没有被析构)的更多相关文章
-
C/C++相对论——C++中为什么要使用异常?
C++中为什么要使用异常? 很多人也许知道C++中的异常机制,很多人也许不知道.很多人知道C中常用的assert,也知道在编译时候指定NODEBUG来忽略它. 对于C语言,使用正常的if-else即是 ...
-
js中页面刷新和页面跳转的方法总结
.js中cookie的基本用法简介 2009-12-15 js中页面刷新和页面跳转的方法总结 文章分类:Web前端 关键字: javascript js中页面刷新和页面跳转的方法总结 1.histor ...
-
javaWeb中servlet开发(4)——servlet跳转
servlet跳转 1.跳转类型 客户端跳转:跳转后地址栏改变,无法传递request范围内属性,是在所有的操作都执行完毕之后才发生跳转的操作,跳转语法是,response.sendRedict() ...
-
页面打开 抛出w3wp.exe 中发生未处理异常
页面打开 抛出w3wp.exe 中发生未处理异常
-
向Oracle中传入数组,批量执行SQL语句
1.首先用PL/SQL创建package create or replace package excuteBatchOperate as type sqlStr_Array ) index by bi ...
-
遇到问题-----JS中设置window.location.href跳转无效(在a标签里或这form表单里)
问题情况 JS中设置window.location.href跳转无效 代码如下: ? 1 2 3 4 5 6 7 8 <script type="text/javascript&quo ...
-
mybatis 中的稍微复杂些的sql语句
mybatis 中的稍微复杂些的sql语句: <?xml version="1.0" encoding="UTF-8" ?> <!DOCTYP ...
-
Spring 中jdbcTemplate 实现执行多条sql语句
说一下Spring框架中使用jdbcTemplate实现多条sql语句的执行: 很多情况下我们需要处理一件事情的时候需要对多个表执行多个sql语句,比如淘宝下单时,我们确认付款时要对自己银行账户的表里 ...
-
union 中可以存储的是不带构造函数的类对象
union 中可以存储的是不带构造函数的类对象 否则不符合逻辑 为什么不符合逻辑?
随机推荐
-
黄聪:Discuz!的SEO优化策略一:如何设置标题 &; 如何去掉Powered by Discuz!尾巴
1.如何设置标题 进入 管理中心 -- 全局 -- SEO设置 -- 论坛 -- 标题 ,设置你的网站标题和描述. PS:有人问keywords要不要设置,其实现在keywords对SEO的影响已经微 ...
-
ocp 1Z0-043 1-60题解析
1.You observe that a database performance has degraded overa period of time. While investigating the ...
-
8.2 C++ AMP advanced concepts
C++ AMP一些更高级的概念: 1. device内存的分配和拷贝. void vecAdd(float* A, float* B, float* C, int n) { array<> ...
-
APP-FND-01706: Error Updating TABLE_NAME In FND_DOCUMENT_SEQUENCES (文档 ID 338026.1)
In this Document Symptoms Cause Solution Applies to: Oracle Order Management - Version 11.5.10.0 and ...
-
前端开发常用 Linux 命令
clear // 清理命令窗口(可简写为cls) exit // 关闭命令窗口 mkdir 文件夹名 // 新建文件夹 cd 文件夹名 // 进入文件夹 cd .. // 返回上一级文件夹目录 rm ...
-
【Codeforces 1120C】Compress String
Codeforces 1120 C 题意:给一个串\(S\),将这个串分成\(t_1..t_m\),如果\(t_i\)在\(t_1..t_{i-1}\)中作为子串出现过,那么这个的代价是\(b\),否 ...
-
【转】win中IDLE选择virtualenv的启动方法
从dos命令行运行.(virtualenv dir)\Scripts\activate.bat脚本激活环境,然后执行: python -m idlelib.idle 摘录:https://blog.c ...
-
无法加载 DLL“ParkCOM.dll”: 找不到指定的模块。 (异常来自 HRESULT:0x8007007E) 终结者
C#调用利用C++写的dll 常遇到的情况是无法加载DLL"***.dll":找不到指定的模块(异常来自HRESULT:0x8007007E)终极解决方法如下: 1.产生原因 可能 ...
-
iOS开发-UIImageView响应点击事件
UIImageView是不能够响应点击事件的,在开发过程中我们需要经常对头像等添加点击事件,上网搜索一番后发现有如下两个方法: 1.找到点击图片Event,添加事件处理函数 UIImageView.u ...
-
Java含有Date的对象序列化网络传输
与短信接口对接时,Date从我这边传输以及在短信平台接收后转换出了问题 传入一个TemplateRequest对象 Feign接口 将含有Date的将要传输的TemplateRequest加上@Req ...