《More Effective C++ 》读书笔记(二)Exception 异常
这事篇读书笔记,只记录自己的理解和总结,一般情况不对其举例子具体说明,因为那正是书本身做的事情,我的笔记作为梳理和复习之用,划重点。我推荐学C++的人都好好读一遍Effective C++ 系列,真是好书啊,对于学完C++ 基础知识的人,这是本高阶秘籍。
笔记
条款 9 - 15 关注的主题是异常。关注1、异常可能引起的资源泄露(强烈推荐使用智能指针)2、异常是如何抛出的和3、异常的成本。目的是写出 exception-safe 的程序。
条款9: 利用 destructor避免资源泄露。
这个条款是说如果异常被抛出到调用端,但是调用端没有catch, 如果调用端是指针,用来析构指针的delete语句可能因为异常被抛出而跳过,导致资源泄露。最好的办法就是不用指针,用临时对象,或者说用行为类似指针的临时对象(为什么非要用类似指针的行为呢?为了多态),临时对象会在对象生存期结束的时候析构,在析构函数中delete(如果有指针的话) 释放资源。这里的原则就是所谓RAII(Resource Acquisition Is Initialization),在具体实践上就是使用智能指针,C++11 中提供了std::shared_ptr 和 std::unique_ptr,目的就是为了避免资源泄露。条款10:在 constructor 内阻止资源泄露。 这个条款举例子说明了如果在对象构造时发生了异常,这个时候因为构造未完成故不会调用该对象的析构函数,该对象的指针成员面临着没有delete 的风险,导致资源泄露。解决办法跟条款9一样,想用指针的时候使用智能指针。
条款11:禁止异常流出destructors 之外。 这个条款是要说明,如果异常发生在destuctor中,不要将其抛出。 理由1是因为如果这个destuctor是因为某个异常而调用的,在这时候再次发生异常并抛出会导致程序 terminate,程序将会终结,也就是最不喜欢看到的程序崩了。处理方式是把异常给吞了,如下面的例子。理由2是如果异常被抛出,引起异常的函数后面的代码都没有被执行,析构函数没有析构完。因此要尽力阻止异常被destrucor 抛出。
~AClass(){
try{
a_function_may_throw_exception();
}catch(...){
// done nothing.
}
}
- 条款12:了解“抛出一个异常excption” 与“传递一个参数”或者“调用一个虚函数”之间的差异。 首先得明确一点, 抛出异常,事实上也是抛出异常对象,看上去跟传递对象参数是很类似的。(1) 但是,异常在抛出的时候总是伴随着对象copy行为(想想这是为什么,提示与局部对象生存期有关),也因此在效率上发生折扣。常见参数的传递的方式有 by value, by reference, by pointer. 不管是 by value 还是 by reference 抛出异常实例都会引起复制,捕捉异常时 by value 还要多复制一次。 throw by pointer 和 pass by pointer。 都是传递指针的副本,千万不要传递一个指向局部对象的指针,否则会获得一个指向已销毁的对象的指针。(2) 传递exception 不会发生隐式类型转化,除非是有型指针转为 void* 或者是继承架构中的转化(catch base 的可以catch derived 的异常),catch 语句中遵循 first fit, 即第一个匹配的就被捕捉,所以 base exception 会拦截 derived excetion。(因此应该让catch derived excaption 的语句放在前面)。
- 条款13:以 by reference 的方式捕捉异常。 无论如何不要用 by pointer 方式捕捉异常; by value 传递会有slice 问题而且比 by reference 多复制一次。综合条款 12 和13 ,结论就是使用 by reference 的方式捕捉异常。
- 条款14:明智运用exception specifications。 这是一把双刃剑,一方面对于函数希望提供什么样的exception 提供了说明,另外也带来了不安全的行为。unexcepted 函数默认终结程序,如果违反了 exception specification 会调用unexception函数。记住1.不要和模板 template 混用;2.不要对回调函数使用exception specification.
Note:
void foo() throw(); // 含义是不抛出异常void foo() throw(A,B,C); // 含义是可能抛出A,B,C 型异常- 书中76 页中介绍了 set_unexpected()函数和将非预期的异常转化为已知异常的技术,可以较为安全的处理unexpected 发生。
- 条款15:了解异常处理(excption handling)的成本。 成本主要是三点:1.为了支持异常,程序需要做大量簿记工作,消耗额外的内存和时间,而且因为只要程序库或者用户代码任何一处用了异常处理,编译器就必须提供对异常处理的支持能力。 2. 编译器实现try语句块和 excpetion specification 带来的代码膨胀和性能损失,2000年之前作者写这本书的时候,得到的消息和测试结果是 5%-10%的损失,不知道现在谁否有提升。 3.抛出异常的损失,可能比正常的函数返回要慢三个数量级。注意,这个只是在发生异常并抛出的时候才有,而异常应该是比较少发生才是。
总结
- 为了异常安全,使用智能指针;
- 析构函数不要抛出异常,应该吞掉;
- 捕捉catch 异常应该 by reference;
- 异常处理是有成本的。(迷思:这些成本如今是否得到优化,或者项目可以容忍?如果我开始一个新项目,我要不要使用异常处理?)
《More Effective C++ 》读书笔记(二)Exception 异常的更多相关文章
- Effective STL 读书笔记
Effective STL 读书笔记 标签(空格分隔): 未分类 慎重选择容器类型 标准STL序列容器: vector.string.deque和list(双向列表). 标准STL管理容器: set. ...
- Effective STL读书笔记
Effective STL 读书笔记 本篇文字用于总结在阅读<Effective STL>时的笔记心得,只记录书上描写的,但自己尚未熟练掌握的知识点,不记录通用.常识类的知识点. STL按 ...
- 《你必须知道的.NET》读书笔记二:小OO有大原则
此篇已收录至<你必须知道的.Net>读书笔记目录贴,点击访问该目录可以获取更多内容. 一.单一职责原则 (1)核心思想:一个类最好只做一件事,只有一个引起它变化的原因 (2)常用模式:Fa ...
- spring揭秘 读书笔记 二 BeanFactory的对象注册与依赖绑定
本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,而且IoC Service Pr ...
- how tomcat works 读书笔记(二)----------一个简单的servlet容器
app1 (建议读者在看本章之前,先看how tomcat works 读书笔记(一)----------一个简单的web服务器 http://blog.csdn.net/dlf123321/arti ...
- ES6读书笔记(二)
前言 前段时间整理了ES6的读书笔记:<ES6读书笔记(一)>,现在为第二篇,本篇内容包括: 一.数组扩展 二.对象扩展 三.函数扩展 四.Set和Map数据结构 五.Reflect 本文 ...
- effective c++读书笔记(一)
很早之前就听过这本书,找工作之前读一读.看了几页,个人感觉实在是生涩难懂,非常不符合中国人的思维方式.之前也有博主做过笔记,我来补充一些自己的理解. 我看有人记了笔记,还不错:http://www.3 ...
- Effective Java读书笔记完结啦
Effective Java是一本经典的书, 很实用的Java进阶读物, 提供了各个方面的best practices. 最近终于做完了Effective Java的读书笔记, 发布出来与大家共享. ...
- spring揭秘 读书笔记 二 BeanFactory的对象注冊与依赖绑定
本文是王福强所著<<spring揭秘>>一书的读书笔记 我们前面就说过,Spring的IoC容器时一个IoC Service Provider,并且IoC Service Pr ...
- 【记】《.net之美》之读书笔记(二) C#中的泛型
前言 上一篇读书笔记,很多小伙伴说这本书很不错,所以趁着国庆假期,继续我的读书之旅,来跟随书中作者一起温习并掌握第二章的内容吧. 一.理解泛型 1.为什么要使用泛型?-----通过使用泛型,可以极大地 ...
随机推荐
- Java中CSS&JS篇基础笔记
HTML就是由一组标签所组成的.HTML的字体标签: <font>标签: 属性:color,size,face HTML的排版标签: h标签:标题标签. p标签:段落标签. b标签:加粗标 ...
- vue项目获取当前地址栏参数(非路由传参)
项目中遇到一个需求,就是另一个管理系统带参直接单纯的跳转跳转到vue pc项目中的某个页面,后再初始化查询数据,参数以地址栏的形式传入 管理系统:打开新地址地址 let obj = { id: 21, ...
- py基础__socket编程
目录 Python基础__socket编程 1.计算机网络 2.socke编程 3.socketserver模块 4.思考 Python基础__socket编程 1.计算机网络 1.OSI网络七层模型 ...
- fail2ban 防暴力破解总结
公司服务器安全问题一直是个令人头疼的问题,许多运维的小伙伴一直在用脚本来监控服务器登录状态,然而脚本编写比较麻烦,今天就给大家推荐一款小而精致的防暴力破解工具 fail2ban ,他可以监控系统日志, ...
- chkconfig设置开机自启动的原理
开机自启动服务的原理$ sshd on #手动设置3级别的开机自启动 [leiyf@leiyangfeng ~] #手动设置3级别的开机自启动,实质是在对应运行级别的目录rc3.d下创建一个sshd的 ...
- Redis之Redis持久化
Redis(Remote Dictionary Server)是一个可持久化的内存.Key-Value数据库. 作为内存数据库,为了防止因服务器断电或系统宕机而引起的数据丢失问题,Redis自带了持久 ...
- php实现银联支付
银联支付用的还是比较少的,而且开发中也没接触多少,不过因为工作项目用银联支付能降低费率,所以还是接入了银联支付.本文支付为银联网关和WAP支付接口. 官方网站SDK&DEMO:https:// ...
- 【八】将日志写入log(glog)
[任务8]将日志写入log(glog) glog简介 glog是google开源的一个日志系统,相比较log4系列的日志系统,它更加轻巧灵活,而且功能也比较完善 glog配置使用资料 下载glog 命 ...
- 《Act with Prudence》读后感
<97 Things Every Should Know>中第一个编程方面的建议 文章链接:行事谨慎 很赞同文章中的观点,在做项目中是要谨慎行事和考虑后果.一直在项目前期考虑不够周到,以至 ...
- go学习之文件读取问题(需更新)
go学习之文件读取问题(需更新) 一,问题: 今天做一个GO广度迷宫问题时,出现了一个奇怪的问题. 就是通过fmt.Fscanf()读取文件时,每行末尾多出一个0. 二,问题代码: 1,输入文件maz ...