异常类型的生命周期

1. throw 基本类型:

int、float、char

这三种类型的抛出和函数的返回传值类似,为参数拷贝的值传递。

 1 int test_1(int num) throw (int, double, char)
2 {
3 if (num == 0)
4 {
5 throw -1;
6 }else if (num == 1){
7 throw 0.01;
8 }else{
9 throw 'A';
10 }
11
12 return 0;
13 }
14
15 int main()
16 {
17 int ret = 0;
18 try
19 {
20 ret = test_1(2);
21 }
22 catch (int error) {
23 printf("捕捉到 int 类型异常:%d", error);
24 }catch (double error) {
25 printf("捕捉到 double 类型异常:%f", error);
26 }catch (char error) {
27 printf("捕捉到 char 类型异常:%c", error);
28 }
29
30 return 0;
31 }

2 throw 字符串类型:

string、char[num]

与普通变量区别不大,字符串抛出的是字符串的地址,如下边的代码:

test() 传1 过去运行结果:

抛出 char * 字符串异常地址为:0097CDB8
char* error = (char*)被捕获异常地址为:0097CDB8

test() 传2 过去运行结果:

抛出 string 字符串异常地址为:00CE5F18
string *error = new string被捕获异常地址为:00CE5F18

抛出字符串与普通变量也没有多大区别,也是值传递,但传的是指针,而且修饰指针的 const 也要严格进行类型匹配。

 1 int test(int num) throw (char *, string)
2 {
3 if(num == 1)
4 {
5 const char* error = "char* error = (char*)"; //修饰指针的 const 也要严格进行类型匹配。
6 printf("抛出 char * 字符串异常地址为:%p\n", error);
7 throw error;
8 }
9 else if (num == 2)
10 {
11 string *error = new string("string *error = new string");
12 printf("抛出 string 字符串异常地址为:%p\n", error);
13 throw error;
14 }
15
16 return 0;
17 }
18
19 int main()
20 {
21 int ret = 0;
22 try
23 {
24 ret = test(1);
25 }
26 catch (const char *error)
27 {
28 printf("%s被捕获", error);
29 printf("异常地址为:%p\n", error);
30 }
31 catch (string *error)
32 {
33 printf("%s被捕获", error->c_str());
34 printf("异常地址为:%p\n", error);
35 //别忘记释放内存
36 delete error;
37 }
38
39 return 0;
40 }

3 throw 类类型异常:

  首先要说明,throw 类类型的最佳方式是:抛出类的匿名对象,使用引用类型捕捉对象,这种方法效率最高,下边将会具体说明。

  throw 类类型的生存周期分几种情况,生存周期的不同与编译器对于类的处理有关,用下方的代码举例:

 1 #include <iostream>
2 #include <string>
3
4 class ErrorException
5 {
6 public:
7 ErrorException();
8 ~ErrorException();
9 ErrorException(const ErrorException& error);
10
11 private:
12 int ID = -1;
13 };
14
15 ErrorException::ErrorException()
16 {
17 ID = 0;
18 printf("ErrorException 构造\n");
19 }
20
21 ErrorException ::~ErrorException()
22 {
23 printf("ErrorException ~析构 (ID:%d)\n", ID);
24 }
25
26 ErrorException::ErrorException(const ErrorException& error)
27 {
28 ID = 1;
29 printf("ErrorException 拷贝构造函数\n");
30 }
31
32 int test(int num) throw (ErrorException)
33 {
34 if (num == 1)
35 {
36 throw ErrorException();      //这里抛出的是匿名对象
37 }
38
39 return 0;
40 }
41
42 int main()
43 {
44 int ret = 0;
45 try
46 {
47 ret = test(1);
48 }
49 catch (ErrorException &error)
50 {
51 printf("捕捉到异常!ErrorException 类型\n");
52 }
53 catch (...)
54 {
55 printf("没有捕捉到异常类型\n");
56 }
57
58 return 0;
59 }

===================================================================================
第49行如果 error 没有引用,运行结果:

ErrorException 构造
ErrorException 拷贝构造函数
捕捉到异常!ErrorException 类型
ErrorException ~析构 (ID:1)
ErrorException ~析构 (ID:0)

说明:调用了两次析构函数,一次是在 36行创建了匿名对象抛出,一次是在49行,因为使用了形参值传递,会进行两个对象的创建。

从ID 的变化可以看出,先析构拷贝构造函数,后析构构造函数。

===================================================================================
第49行如果 error 使用了引用,运行结果:

ErrorException 构造
捕捉到异常!ErrorException 类型
ErrorException ~析构 (ID:0)

说明:使用引用的话,将会少创建一个对象,是36行的临时匿名对象的地址进行抛出,捕捉时直接捕捉引用,不用再次创建,这种效率最高。

===================================================================================
第36行,如果先创建对象,然后37行 throw 对象,50行用形参接收,则会变得更加低效,这一切要说下编译器在背地里做的很多事情,如下代码:

 1 /* . . . 省略 . . . */
2 int test(int num) throw (ErrorException)
3 {
4 if (num == 1)
5 {
6 ErrorException error;          //进行对象创建
7 throw error;               //进行对象抛出
8 }
9
10 /* . . . 省略 . . . */
11 try
12 {
13 ret = test(1);
14 }
15 catch (ErrorException error)        //使用形参接收
16 {
17 printf("捕捉到异常!ErrorException 类型\n");
18 }

运行结果:

ErrorException 构造
ErrorException 拷贝构造函数 
ErrorException 拷贝构造函数
ErrorException ~析构 (ID:0)
捕捉到异常!ErrorException 类型
ErrorException ~析构 (ID:1)
ErrorException ~析构 (ID:1)

说明:

ErrorException 构造         ------------> 36 行创建对象
ErrorException 拷贝构造函数      -----------> 由于 36 行创建的对象作用域在函数内部,但异常要继续往外抛,编译器会创建一个临时的匿名对象
ErrorException 拷贝构造函数     ------------> 第50行创建的error,用上边生成的临时的匿名对象进行拷贝。
ErrorException ~析构 (ID:0)     ------------> 由于 test 函数结束,36行创建的对象被析构。
捕捉到异常!ErrorException 类型    -----------> 进入到 52 行打印。
ErrorException ~析构 (ID:1)     ------------> 第50行创建的error对象,走出作用域销毁。
ErrorException ~析构 (ID:1)     ------------> 离开第50行的 catch 的作用域时 临时的匿名对象被销毁。

===================================================================================

  如果使用指针进行异常抛出,大同小异,用上边的代码举例,要注意的就是内存的释放,如下代码:

 1 /* . . . 省略 . . . */
2 int test(int num) throw (ErrorException)
3 {
4 if (num == 1)
5 {
6 throw new ErrorException();                    //动态内存分配
7 }
8
9 /* . . . 省略 . . . */
10 catch (ErrorException *error)
11 {
12 printf("捕捉到异常!ErrorException 类型\n");
13 delete error;                            //注意释放内存
14 }

  运行结果:

ErrorException 构造
捕捉到异常!ErrorException 类型
ErrorException ~析构 (ID:0)

   ===================================================================================

1. 异常处理的三个关键字

点击查看

2. 异常处理的基本语法

点击查看

3.异常处理接口声明

点击查看

4.异常类型的生命周期

4.1 throw 基本类型:

点击查看

4.2 throw 字符串类型:

点击查看

4.3 throw 类类型异常:

点击查看

5.异常和继承

点击查看

6.异常处理的基本思想

点击查看

7.标准库里的异常类

点击查看

C++异常之四 异常类型的生命周期的更多相关文章

  1. 异常情况下的Activity生命周期分析

    情况1:资源相关的系统配置发生改变 资源相关的系统配置发生改变,举个栗子.当前Activity处于竖屏状态的时候突然转成横屏,系统配置发生了改变,Activity就会销毁并且重建,其onPause, ...

  2. 《深入Java虚拟机学习笔记》- 第7章 类型的生命周期/对象在JVM中的生命周期

    一.类型生命周期的开始 如图所示 初始化时机 所有Java虚拟机实现必须在每个类或接口首次主动使用时初始化: 以下几种情形符合主动使用的要求: 当创建某个类的新实例时(或者通过在字节码中执行new指令 ...

  3. Java类型的生命周期

    以上就是我今天没有总结学习类加载器时候对类加载器仅有的知识,虽然有个大概印象,但是还是有点模糊.今天一口气总结一下,参考文献我就不列举了.本文不生产知识,只是知识的搬运工. 静态.class文件到内存 ...

  4. JVM 类型的生命周期学习

    Java虚拟机通过装载.连接和初始化一个JAVA类型,使该类型可以被正在运行的JAVA程序所使用,其中,装载就是把二进制形式的JAVA类型读入JAVA虚拟机中:而连接就是把这种读入虚拟机的二进制形式的 ...

  5. Autofac容器对象实例的几种生命周期类型

    实例范围决定了如何在同一服务的请求之间共享实例. 请注意,您应该熟悉生命周期范围的概念,以便更好地理解此处发生的情况. 当请求服务时,Autofac可以返回单个实例(单实例作用域),新实例(每个依赖作 ...

  6. 05 Maven 生命周期和插件

    Maven 生命周期和插件 除了坐标.依赖以及仓库之外, Maven 另外两个核心概念是生命周期和插件.在有关 Maven 的日常使用中,命令行的输入往往就对应了生命周期,如 mvn package ...

  7. C++异常之五 异常和继承

    异常和继承 异常也是类,我们可以创建自己的异常类,在异常中可以使用(虚函数,派生,引用传递和数据成员等), 下面用一个自制的数组容器Vector,在对Vector初始化时来对Vector的元素个数进行 ...

  8. ASP.NET 页生命周期

    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维护状态.运行事件处理程序代码以及进行 呈现.了解页生命周期非常重要,因为这样 ...

  9. ASP.NET 页生命周期概述

    ASP.NET 页生命周期概述 Visual Studio 2005    ASP.NET 页运行时,此页将经历一个生命周期,在生命周期中将执行一系列处理步骤.这些步骤包括初始化.实例化控件.还原和维 ...

随机推荐

  1. 微信公众号平台Url Token EncodingAESKey 注意点

    最近公司让我开发微信公众号平台扫码登录,同步用户信息于PC端,所做的过程当中遇到了一些坑,做完了就总结一下需要注意的点,如若大家开发过程中遇到同样的问题,可以借鉴! 第一:配置域名 作用:配置域名为了 ...

  2. YH高校集中用电管理网上查询系统POST注入漏洞

    1.burpsuite 抓包保存为1.txt POST /apartsearch.asp HTTP/1.1 Host: 2*0.86.2**.69 User-Agent: Mozilla/5.0 (W ...

  3. 【转】AWVS扫描小技巧

    1.文件头加 Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html) 可以绕过狗,waf ...

  4. 微信支付回调 敏感信息解密 v3 php

    今天博主用了一波微信的v3版本的支付,支付成功后发现回调跟v2的完全不一样,于是去看了了一波v3的文档,发现信息是经过加密的,需要解密才能获取的到 但是最悲催的是文档上没写怎么解密的,经过了一下午的百 ...

  5. 关于Redis的一些思考

    1.从Java语言考虑,已经有ConcurrentHashMap等并发集合类了,与Redis相比,区别于差异在哪? 一直有这么个疑问,今天有搜了很久,很巧,搜到个有同样想法的问答,如下: When p ...

  6. 面试官:别的我不管,这个JVM虚拟机内存模型你必须知道

    前言 说jvm的内存模型前先了解一下物理计算机的内存处理. 物理计算器上用户磁盘和cpu的交互,由于cpu读写速度速度远远大于磁盘的读写速度速度,所以有了内存(高速缓存区).但是随着cpu的发展,内存 ...

  7. go-zero 如何扛住流量冲击(二)

    本篇文章承接上一篇go-zero 如何扛住流量冲击(一). 上一篇介绍的是 go-zero 中滑动窗口限流,本篇介绍另外一个 tokenlimit ,令牌桶限流. 使用 const ( burst = ...

  8. 如何用CDR做出毛笔字效果

    不仅仅是水墨字,毛笔字在CDR中的制作也是很简单的.一般来讲,水墨字其实跟毛笔字有相通之处,也可以说毛笔字是水墨字的一种,在CDR中的实现也是既简单又实用的. 方法一:艺术笔工具 艺术笔工具是比较便捷 ...

  9. pdfFactory全景手柄使用方法介绍

    当文档中存在一些照片,或使用的字体过小时,大家可能会使用放大的功能,将文档的页面进行放大处理.此时,页面就会仅显示局部,为了查看页面的其他内容,就要使用到全景手柄来移动页面. pdfFactory的全 ...

  10. 在CorelDRAW中为对象添加块阴影效果

    我们可以使用CorelDRAW来绘制矢量图形,在勾画出简单的图形后,往往还需要对它们进行一些或简单或复杂的处理,以增加一定的艺术效果.CDR中可供选择的效果有很多,作用的对象可以是文字,也可以是图案. ...