【异常机制】异常抛出变量的生命周期

简介: 【异常机制】异常抛出变量的生命周期

当我们throw出类对象时,使用catch捕获异常时有三种选择,分别是捕获对象元素、捕获引用和捕获指针,那么这三种情况下,捕获到的变量是如何分配内存,他的生命周期又是如何呢,首先结论如下:

  • 捕获类对象的元素:调用拷贝构造函数把抛出的对象元素拷贝给catch的参数对象元素,调用拷贝构造函数;
  • 捕获类对象的引用:catch语句中的对象直接使用抛出的对象;
  • 捕获类对象的指针:需要手动new和delete控制内存;

结论如上,下面通过一个程序详细探究(提示:因为catch严格按照类型匹配进行接异常,所以catch元素和catch引用不能同时出现)。

1. #include <iostream>
2. using namespace std;
3. 
4. class pIsNULL
5. {
6. public:
7.  pIsNULL()
8.  {
9.    cout << "pIsNULL 无参构造函数" << endl;
10.   }
11.   //pIsNULL(pIsNULL& p)
12.   //错误  C2440 “throw” : 无法从“pIsNULL”转换为“pIsNULL”
13.   //错误(活动)  E0334 类 "pIsNULL" 没有适当的复制构造函数 
14.   pIsNULL(const pIsNULL& p) //拷贝构造函数要加 const
15.   {
16.     cout << "pIsNULL 拷贝构造函数" << endl;
17.   }
18.   ~pIsNULL()
19.   {
20.     cout << "pIsNULL 析构函数" << endl;
21.   }
22. public:
23.   void print_err_type()
24.   {
25.     cout << "异常原因:指针指向NULL" << endl;
26.   }
27. };
28. 
29. void print_str(char* str)
30. {
31.   if (str == NULL)
32.   {
33.     throw pIsNULL(); //调用无参构造函数
34.   }
35.   cout << str << endl;
36. }
37. 
38. void TestFunc1()
39. {
40.   char buf1[] = "hello";
41.   char* buf2 = NULL;
42. 
43.   try
44.   {
45.     print_str(buf2);
46.   }
47.   catch (pIsNULL e) //调用拷贝构造函数,将 throw 出的对象复制给 e
48.   {
49.     e.print_err_type();
50.   }
51.   catch (...)
52.   {
53.     cout << "未知异常" << endl;
54.   }
55. }
56. 
57. void TestFunc2()
58. {
59.   char buf1[] = "hello";
60.   char* buf2 = NULL;
61. 
62.   try
63.   {
64.     print_str(buf2);
65.   }
66.   catch (pIsNULL& e) //不会调用拷贝构造函数
67.   {
68.     e.print_err_type();
69.   }
70.   catch (...)
71.   {
72.     cout << "未知异常" << endl;
73.   }
74. }
75. 
76. void print_str2(char* str)
77. {
78.   if (str == NULL)
79.   {
80.     throw new pIsNULL;
81.   }
82.   cout << str << endl;
83. }
84. 
85. void TestFunc3()
86. {
87.   char buf1[] = "hello";
88.   char* buf2 = NULL;
89. 
90.   try
91.   {
92.     print_str2(buf2);
93.   }
94.   catch (pIsNULL* e)
95.   {
96.     e->print_err_type();
97.     delete e;
98.   }
99.   catch (...)
100.  {
101.    cout << "未知异常" << endl;
102.  }
103. }
104. 
105. int main()
106. {
107.  TestFunc1(); //用对象元素接异常
108.  //TestFunc2(); //用引用接异常
109.  //TestFunc3(); //用指针接
110. 
111.  system("pause");
112.  return 0;
113. }

分别在主函数中调用三个测试函数,观察打印结果:

①在主函数中调用第一个测试函数,用元素捕获异常

TestFunc1(); //用对象元素接异常

打印结果如下

可以看到,在catch的时候会将throw处构造的对象通过拷贝构造函数复制给catch语句中的元素e,因为这里一共有两个对象,所以在异常结束时会调用两次析构函数,分别析构两个对象。

②在主函数调用第二个测试函数,用引用捕获异常

TestFunc2(); //用引用接异常

运行结果如下

使用引用捕获异常的时候会直接使用throw处构造的对象,所以不会调用拷贝构造函数,只调用一次析构函数

③在主函数调用第三个测试函数,用指针捕获异常

TestFunc3(); //用指针接

抛出指针类型的异常最好手动new和delete来管理内存。


相关文章
|
6月前
|
算法 编译器 C语言
【C++ 异常】C++ 标准库异常类及其应用
【C++ 异常】C++ 标准库异常类及其应用
76 0
|
6月前
|
Java C++ Spring
解决NoUniqueBeanDefinitionException异常的方法
了解Spring框架中`NoUniqueBeanDefinitionException`异常的原因和解决方案。此异常发生在容器内有多个相同类型的bean时,Spring无法决定注入哪个bean。解决方法包括:使用`@Primary`注解标记首选bean,利用`@Qualifier`注解配合`@Autowired`、`@Resource`、`@Inject`或`@Value`指定bean名称。选择哪种方法取决于业务需求和具体场景,预防措施是避免创建多个同类型bean或使用`@Primary`注解。
229 0
|
6月前
|
Java UED
Java中的异常处理:捕获、声明与抛出
Java中的异常处理:捕获、声明与抛出
138 0
|
13天前
|
安全 Java 测试技术
如何避免静态变量初始化中的异常
在Java中,静态变量初始化时可能会遇到异常。为避免此类问题,可以采取以下措施:1. 使用静态代码块进行初始化;2. 确保初始化逻辑简单且安全;3. 捕获并处理可能的异常。这些方法能有效提高程序的健壯性和稳定性。
|
3月前
|
Java 编译器 数据库连接
|
4月前
|
Java 程序员 API
Java异常类型及异常处理方式
Java异常类型及异常处理方式
|
Java 开发者
JAVA异常类异常抛出处理
JAVA异常类异常抛出处理
135 0
|
Java
编写一个程序,它能导致JVM抛出一个OutOfMemoryError,然后捕获和处理这个异常
编写一个程序,它能导致JVM抛出一个OutOfMemoryError,然后捕获和处理这个异常
203 0
有关异常的处理、捕获、抛出、自定义
有关异常的处理、捕获、抛出、自定义
104 0