c++中,当异常遇见构造与析构
2017-12-03 19:59
197 查看
c++中,当异常遇见构造与析构,会碰撞出什么样的火花?
本来应该说,当构造与析构遇见异常的,但是好像念起来不太顺。就改了下。哈哈。
我们知道资源是有限的,申请资源和释放资源是要配对执行的。有申请无释放,就会造成资源泄露。
废话不多说,先上代码,如下是一个正常的简单代码。先了解一下,之后再进行改造分析。
B类中有一个A类的对象指针。声明下:这个例子中的资源,就是B类中A类指针所指向的内存。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/37bb28f0b99bade85bc4638668a60ec1)
代码的运行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/e8bf930d7a703d5c28154f52316c5ecf)
1. 构造函数抛异常
1.1. 在B的构造中加异常——未申请资源时抛异常。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/cbee642ee8c55f915034eccaa3fb4aab)
执行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/c249cdcbbef5be0adc67490aa50e4e7b)
可以看出,B类构造未完成,但是也没有申请资源,所以并未出现内存泄露。
1.2 在B的构造中加异常——申请资源后抛异常。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/ce6af2f06aeea3124aa28f351520417d)
执行结果如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/363e9a397c9d17eac621c4d187df4a7e)
可以看出,B类构造开始,在A构造完成后,抛也异常,并成功捕获。
但是:此时并没有调用B类的析构函数,也就没有析构已经构造好的A对象,造成构造析构不一致,内存泄露!!!
结论:
1. 构造函数是可以抛异常的。
2. 构造函数中,如果有申请资源,那么在申请资源后抛异常,而没有在构造函数内部进行捕获异常并释放资源,就会造成资源泄露。如上面的内存泄露。
3. 个人理解,构造函数中如果有申请资源的动作,一定不要轻易抛出异常,最好在内部进行异常消化。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/407f7af9b84f5a18ef980f9470bfe3db)
不让内部的异常抛外面去。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/1a80e87fa96f2225959f72367bff6de8)
上面只是以最简单的方式说明,如果完善,可以处理具体异常类型,也可以加RAII机制,如scope_guard之类的处理。
2. 析构函数抛异常
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/884c7de10aea788c5830d12588088507)
看运行结果,直接就抛外面来了,core掉了!!!捕获异常都没捕获住!!!
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/935cba92b14b45ed3c0f1b04f6ac5046)
查看下core文件,函数调用栈如下:
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/ea718d015da8239a2d7331d745b210f2)
那就没什么好讲的了,c++的异常处理机制导致的。具体细节逻辑,这里不阐述。
结论:
2 析构函数中产生的异常,抛出后,在析构函数外无法捕获,程序会直接崩溃!
2 定义析构函数时,里面的异常不能往外抛,应该在析构函数中捕获并正确处理。注意这里说的是捕获并正确处理,不是说捕获后就不管了,不管那叫掩盖错误,程序运行下去甚至会有比崩溃更严重的后果。
![](https://oscdn.geek-share.com/Uploads/Images/Content/201910/21/fafebf5a6f7c28a46336c68fe4c4dba4)
如下结果运行正常!
本来应该说,当构造与析构遇见异常的,但是好像念起来不太顺。就改了下。哈哈。
我们知道资源是有限的,申请资源和释放资源是要配对执行的。有申请无释放,就会造成资源泄露。
废话不多说,先上代码,如下是一个正常的简单代码。先了解一下,之后再进行改造分析。
B类中有一个A类的对象指针。声明下:这个例子中的资源,就是B类中A类指针所指向的内存。
代码的运行结果如下:
1. 构造函数抛异常
1.1. 在B的构造中加异常——未申请资源时抛异常。
执行结果如下:
可以看出,B类构造未完成,但是也没有申请资源,所以并未出现内存泄露。
1.2 在B的构造中加异常——申请资源后抛异常。
执行结果如下:
可以看出,B类构造开始,在A构造完成后,抛也异常,并成功捕获。
但是:此时并没有调用B类的析构函数,也就没有析构已经构造好的A对象,造成构造析构不一致,内存泄露!!!
结论:
1. 构造函数是可以抛异常的。
2. 构造函数中,如果有申请资源,那么在申请资源后抛异常,而没有在构造函数内部进行捕获异常并释放资源,就会造成资源泄露。如上面的内存泄露。
3. 个人理解,构造函数中如果有申请资源的动作,一定不要轻易抛出异常,最好在内部进行异常消化。
不让内部的异常抛外面去。
上面只是以最简单的方式说明,如果完善,可以处理具体异常类型,也可以加RAII机制,如scope_guard之类的处理。
2. 析构函数抛异常
看运行结果,直接就抛外面来了,core掉了!!!捕获异常都没捕获住!!!
查看下core文件,函数调用栈如下:
那就没什么好讲的了,c++的异常处理机制导致的。具体细节逻辑,这里不阐述。
结论:
2 析构函数中产生的异常,抛出后,在析构函数外无法捕获,程序会直接崩溃!
2 定义析构函数时,里面的异常不能往外抛,应该在析构函数中捕获并正确处理。注意这里说的是捕获并正确处理,不是说捕获后就不管了,不管那叫掩盖错误,程序运行下去甚至会有比崩溃更严重的后果。
如下结果运行正常!
相关文章推荐
- C++中异常处理中的构造和析构
- 对C++中异常处理中的构造和析构的认识
- C++中异常处理中的构造和析构
- 浅析C++中异常类对象的构造与析构
- C++不能中断构造函数来拒绝产生对象(在构造和析构中抛出异常)
- c++构造和析构能不能抛异常的总结!
- c++构造和析构能不能抛异常的问题!
- C++构造,析构,友元类,对象,static成员,复制构造函数,运算符重载杂谈
- 【C++学习历程3】对象的构造和析构
- 10异常处理3.异常处理中的构造与析构
- C++基础:四大基本函数,构造,析构,拷贝构造,赋值函数
- [读书笔记] 深入探索C++对象模型-第五章-构造、析构、拷贝语义学(下)
- C++ 构造/析构函数中的异常处理
- C++构造与析构(7) - 数据成员的初始化
- C++构造与析构(15) - 为何拷贝构造函数必须为const
- C++ 继承的构造与析构
- C++之类的构造与析构(一)
- Primer plus C++ 第十章 对象和类_类的设计进化_构造与析构
- C++对象的构造、赋值和析构
- C++的构造和析构顺序