c++之别让异常逃离析构函数
关于
- 本文代码演示环境: VS2017.
- 代码写的够不规范,目的是为了缩短文章篇幅.
- 本文主要是为了加深印象,写了好多次的代码,还是忘记了这茬。。。。 之前上传到github的代码会慢慢改过来。
- 本文知识要点来自:《Effective C++》
1.析构函数中出现异常
析构函数中出现异常,异常可能来自自身,也可能是析构其他对象是传下来的。先看个例子
class YYY
{
public:
~YYY()
{
// 自己手动抛出一个异常。用来模拟异常出现在析构函数
throw 1;
}
};
正如注释中说的,析构函数中,手动抛出异常。
代码语法也正确,当执行析构函数时,程序出现了错误,并中止了程序的运行。 程序错误 如下:

图中可以看出,调用函数abort函数(终止了程序)
当使用VS2017编译这份代码时,编译器也给出了警告和提示:
1>XXXXXXX\consoleapplication2.cpp(775): warning C4297: “YYY::~YYY”: 假定函数不引发异常,但确实发生了
1>XXXXXXX\consoleapplication2.cpp(775): note: 析构函数或释放器具有一个(可能是隐含的)非引发异常规范
总结
- 可见,但析构函数出现异常,程序会自动终止。
- 应该避免析构函数出现异常。
2.避免析构函数出现异常。
- 《Effective C++》的意见:析构函数应该吞下不传播异常,或者结束程序,而不是吐出异常;如果要处理异常应该在非析构的普通函数处理
照做
class YYY
{
public:
~YYY()
{
uninit();
}
private:
// 析构前调用
void uninit()
{
try
{
// 自己手动抛出一个异常。
throw 1;
}
// 吞并所有异常。
catch (...)
{
std::cout << "void YYY::uninit() exception\n\n";
}
}
};
- 这里,定义了一个函数Uninit,处理异常。还是手动模拟抛出一个异常。接着,析构函数再调用该函数,这样就将处理异常放在了析构函数之外。
- 运行结果

可见,同样的代码,这次正常运行了。 虽然抛出了异常,但是类YYY将其吞下。避免析构异常调用abort函数终止程序。
最后
Note: 不要让异常逃离析构函数。
c++之别让异常逃离析构函数的更多相关文章
- EC读书笔记系列之4:条款8 别让异常逃离析构函数
条款8 别让异常逃离析构函数 记住: ★析构函数绝对不要吐出异常.若一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序. ★若客户需对某个操作函数运行期间 ...
- Effective C++ 条款08:别让异常逃离析构函数
1.别让异常逃离析构函数的原因 <Effective C++>第三版中条款08建议不要在析构函数中抛出异常,原因是C++异常机制不能同时处理两个或两个以上的异常.多个异常同时存在的情况下, ...
- Effective C++_笔记_条款08_别让异常逃离析构函数
(整理自Effctive C++,转载请注明.整理者:华科小涛@http://www.cnblogs.com/hust-ghtao/) C++并不禁止析构函数吐出异常,但它不鼓励你这样做.考虑如下代码 ...
- 《Effective C++》——条款08:别让异常逃离析构函数
考虑如下代码: class Widget{ public: ... ~Widget(){...}//假设这个可能吐出一个异常 }; void doSomething() { std::vector&l ...
- Effective C++ 条款八 别让异常逃离析构函数
class DBConn //这个class用来管理DBConnction对象 { public: //自己设计一个新的DBConn接口 方法3 void close() { db.close() ...
- EC笔记,第二部分:8.别让异常逃离析构函数
1.为何析构函数不应该抛出异常? 有两种情况: 1).假设析构函数中有众多语句,而第一条语句抛出异常(或者其他语句),那么抛出异常以后的语句就得不到执行.而通常我们在析构函数中写的是清理资 ...
- Effective C++ -----条款08: 别让异常逃离析构函数
析构函数绝对不要吐出异常.如果一个被析构函数调用的函数可能抛出异常,析构函数应该捕捉任何异常,然后吞下它们(不传播)或结束程序. 如果客户需要对某个操作函数运行期间抛出的异常作出反应,那么class应 ...
- [Effective C++ --008]别让异常逃离析构函数
这章非常容易理解:因为C++并不禁止析构函数吐出异常,只是不鼓励这样做而已. 一.原因 假设我们有10个装着鸡蛋的容器,而且现在我们还想着把它在析构函数打烂. class Egg { public : ...
- NO.7:别让异常逃离析构函数
1.析构函数绝对不要吐出异常,如果一个析构函数可能抛出异常,析构函数应该捕获任何异常,然后要么吞下它们或者退出程序 2.如果用户需要对析构内的可能抛出异常的操作做出反应,则应该将操作放入除析构函数外的 ...
随机推荐
- UOJ 266 - 【清华集训2016】Alice和Bob又在玩游戏(SG 定理+01-trie)
题面传送门 神仙题. 首先注意到此题的游戏是一个 ICG,故考虑使用 SG 定理解决这个题,显然我们只需对每个连通块计算一遍其 SG 值异或起来检验是否非零即可.注意到我们每删除一个点到根节点的路径后 ...
- ZAQI
mysql> CREATE TABLE emploee ( -> name CHAR(64) NOT NULL, -> email CHAR(64), -> password ...
- seqtk抽取测序数据
做数据比较的时候,由于同一个样本测序数据量不一致,需要抽取数据,控制数据量基本一致. 自己写脚本速度较慢,后面发现一个不错的工具:seqtk 原始数据抽取 如果只控制原始数据量一致,过滤低质量数据后直 ...
- linux中对errno是EINTR的处理
慢系统调用(slow system call):此术语适用于那些可能永远阻塞的系统调用.永远阻塞的系统调用是指调用有可能永远无法返回,多数网络支持函数都属于这一类.如:若没有客户连接到服务器上,那么服 ...
- Identity Server 4 从入门到落地(七)—— 控制台客户端
前面的部分: Identity Server 4 从入门到落地(一)-- 从IdentityServer4.Admin开始 Identity Server 4 从入门到落地(二)-- 理解授权码模式 ...
- OC中的结构体
一.结构体 结构体只能在定义的时候进行初始化 给结构体属性赋值 + 强制转换: 系统并不清楚是数组还是结构体,需要在值前面加上(结构体名称) +定义一个新的结构体,进行直接赋值 + ...
- Controller返回类的自动识别,WEB-INF,jsp位置
Controller: @Controller@RequestMapping("/params")public class ParamsController { @RequestM ...
- mysql安装 报错解决
换了新电脑,重新安装了一下mysql,安装过程出现了一些错误,在此记录一下: 参考菜鸟教程:https://www.runoob.com/mysql/mysql-install.html 1.下载my ...
- 【C#】【MySQL】【GridView】删除出现Parameter index is out of range
[编程语言]C# [数据库]MySQL [控件]GridView [问题描述]GridView控件中自带[删除],[编辑],[选择],三个按钮[编辑],[选择]正常使用,但是在使用删除时,却报错Par ...
- Java 多线程的一次整理
一天没有出过家门,实属无聊,没事瞎写写 1. 基本概念 1.1 多进程和多线程的概念 程序是由指令和数据组成,指令要运行,数据要加载,指令被 CPU 加载运行,数据被加载到内存,指令运行时可由 CPU ...