【Effective C++】读书笔记 Part5 实现

条款29:为异常安全而努力是值得的

当异常被抛出时,待哟异常安全性的函数会:

  1. 不泄漏任何资源。
  2. 不允许数据败坏。

异常安全函数提供以下三个保证之一

  1. 基本承诺。如果异常被抛出,程序内的任何事物仍然在有效状态下。没有任何对象或数据结构会因此而败坏。所有对象都处于一种内部前后一致的状态,但是程序中哦个对象的现实状态不可预料。
  2. 强烈保证。如果异常被抛出,程序状态不会被改变。调用这样的函数只有如下两种情况:函数调用成功,就是完全成功,如果函数调用失败,程序会回复到“调用函数之前”的状态。
  3. 不抛出异常。函数保证绝不抛出异常,因为它们总能够完成它们所承诺的功能。

对于任何函数,都应该尽量保证异常安全,注意下面亮点:

  1. 不要为了表示某件事情发生而改变对象状态,除非那件事情已经真的发生了。
  2. copy-swap策略,往往能够帮助我们实现“强烈保证”的异常安全,但是“强烈保证”并非堆所有函数都可实现或具备现实意义,有因为效率和复杂度的关系,“基本承诺”的异常安全就已经够用了。
  3. 函数提供的的“异常安全保证”通常最高只等于其所调用之各个函数的“异常安全保证”中的最弱者。

条款30:透彻了解inlining的里里外外

1. 基础知识

Inline函数会给我们带来许多的好处,它们看起来像函数,动作函数,比洪好的多,可以调用它们但是又不需要承受函数调用所招致的额外开销。编译器最优化设计通常被设计用来浓缩那些“不含函数调用”的代码,所以当使用inline函数时候,编译器就有能力对它执行语境相关最优化。

inline函数通常是将相应的函数本体直接展开在调用点,而舍弃了函数调用。如果函数本体过大,这就会导致目标代码(object code)增大,造成代码膨胀。但是如果inline函数本体很小,编译器针对“函数本体”所产生的目标代码可能比针对“函数调用”产生的目标代码所产出的目标代码更小,同时也拥有了inline函数所带来的效率。

2. inline函数的inlining

inline关键字可以用来修饰普通函数和类的成员函数。对于inline普通函数通常需要将函数定义及其实现放置在头文件中,因为对于大多数build environment而言,都是在编译过程中进行inlining(inline展开),所以对于一个inline函数或者是inline成员函数,都需要定义在头文件内,从而保证编译器在编译阶段就已经拥有了inline函数的定义。

3. 编译器视情况来选择是否inlining

除此之外,inline函数只是向编译器提出一个申请,编译器可以选择忽略。大多数编译器都会拒绝将太过复杂的函数(如带有循环或者递归)进行inlining,而对于所有虚函数也都会拒绝inlining。

由于对于所有的虚函数而言,显然只有在运行时候才能够确定具体执行的函数本体,但是对于inline函数而言,则是在编译阶段就需要了解到函数的具体定义。显然对于virtual函数,编译器无法将其inlining。

除此之外,inline函数(非成员函数)其作用于一般都是在文件作用域内,因为inline函数如果都能够在调用处展开,编译器也没有必要对此函数创建符号,并且在代码段中存储函数的二进制指令(函数本体)。

但是,有些情况下,虽然编译器能够对函数进行inlining,但是也会生成一个函数本体。

如当我们对一个inline函数进行取地址的时候,这时候就强迫编译器生成一个相应的outlined函数本体。

另外,如果我们通过一个函数指针来调用inline函数,编译器往往不会将其inlining,因此根据调用函数的方式不同,编译器会视情况来决定是否inlining。

inline void f(){……}//假设编译器会inline函数f
void ( *pf)()=f;//指向函数的指针f();//这个调用会被inlined,因为是正常调用pf();//这个调用可能不会被inlined,因为它是通过函数指针达成

4. inline函数与构造和析构函数

构造函数和析构函数往往都不适合作为inline函数。虽然在许多情况下,构造函数的函数体都可能十分小,或者为空。

但是看看C++标准对于对象被构建和销毁时候所保证的的事情:

  1. 当你使用new的时候,动态创建的对象被构造函数自动初始化 。
  2. 当你使用delete的时候,对应的析构函数将被调用。
  3. 当你创建一个对象的时候,其每一个base class及其每一个成员变量都会被自动构造。
  4. 当你销毁一个对象的时候,反向顺序的析构行为会自动发生。
  5. 如果有个异常在构造函数内抛出,该对象已经构造好的那一部分会自动析构。

等等。

这就注定了本来可能函数体非常小的构造函数和析构函数,在经过编译器的处理后就会变得非常复杂,显然就不适合将其进行inlining。

5. inline函数与函数升级

对于程序库中如果不存在non-inline函数,那么客户端程序一般只需要重新链接即可,并不需要重新编译。

如果客户端程序动态链接程序库,那么可能就无需做任何改变就可直接使用升级了版本的程序库。

但是如果将程序库设计为inline函数会给我们的客户端程序带来一定的冲击。主要是客户端程序中,将包含我们程序库中的inline函数的展开,因而如果程序库升级了inline函数,那么客户端代码也必须要重新编译。这个过程量就会显著增大。

6. inline函数与调试

最后一点要注意的是,inline函数往往无法和调试器完美配合,因为在代码执行中,inline函数已经被展开,显然你无法在一个已经不存在的函数设置断点。

7. 小结

  1. 请将大多数inline函数限制在小型,被频繁调用的函数身上。这可使日后的调试过程和二进制升级更容易,也可使潜在的代码膨胀问题最小化,使得程序的速度提升机会最大化。
  2. 不要只是因为function template出现在头文件中,就将它们声明为inline.

【Effection C++】读书笔记 条款29~条款30相关推荐

  1. 读书笔记_Effective_C++_条款三十一:将文件间的编译依存关系降至最低(第二部分)...

    下面再来看书,去理解书上说的Handler classes就简单多了,我们大概过一下. 假设我们要写一个Person类,如下: 1 class Person 2 { 3 private: 4 stri ...

  2. 读书笔记_Effective_C++_条款七:为多态基类声明virtual析构函数

    严格来说,多态分为编译时多态和运行时多态,编译时多态是函数的重载,而运行时多态则是迟绑定技术,即根据基类指针或引用的实际指向来决定采取何种行动,一般来说,多态特指运行时多态.下面我们来举有关C++多态 ...

  3. 读书笔记_Effective_C++_条款十九:设计class犹如设计type

    这里初看到"class"和"type",感觉他们是说的是同一样东西,但仔细读了一下,两者在文中还是有区别的.class侧重于自定义的类,而type侧重于系统预定 ...

  4. 读书笔记_Effective_C++_条款二十四: 若所有参数皆需类型转换,请为此采用non-member函数...

    class A { private:int a; public:A(int x) :a(x){}A operator*(const A& x){return A(a*x.a);} };int ...

  5. 读书笔记 effective c++ Item 30 理解内联的里里外外 (大师入场啦)

    正文 最近北京房价蹭蹭猛涨,买了房子的人心花怒放,没买的人心惊肉跳,咬牙切齿,楼主作为北漂无房一族,着实又亚历山大了一把,这些天晚上睡觉总是很难入睡,即使入睡,也是浮梦连篇,即使亚历山大,对C++的热 ...

  6. 【Effection C++】读书笔记 条款28:避免返回handles指向对象内部成分

    [Effective C++]读书笔记 Part5 实现 条款28:避免返回handles指向对象内部成分 避免返回handles(包括references,指针,迭代器)指向对象内部.遵守这个条款可 ...

  7. 【Effection C++】读书笔记 条款27:尽量少做转型动作

    [Effective C++]读书笔记 Part5 实现 条款27:尽量少做转型动作 C++中的类型转换语法 类型转换语法主要有三种不同的形式: (T)expression //将expression ...

  8. 【Effection C++】读书笔记 条款26:尽可能延后变量定义式的出现时间

    [Effective C++]读书笔记 Part5 实现 条款26:尽可能延后变量定义式的出现时间 非循环中的变量定义 尽量延后变量定义式的出现时间,主要包括两个方面: 直到必须使用变量的时候才对其进 ...

  9. 【Effection C++】读书笔记 条款01~条款04

    [Effection C++]读书笔记 Part1 让自己习惯C++ 条款01:视C++为一个语言联邦 将C++视为一个由相关语言组成的联邦.在其某个次语言中,各种守则简单易懂,容易记住.但当从一个次 ...

最新文章

  1. center os7 安装mysql
  2. 余额宝 vs. P2P网贷,谁更有生命力?
  3. python elif 用法_Python入门高级教程--Python 条件语句
  4. 小波滤波器与其他滤波器的区别_小波变换(六):小波变换在机器学习中的应用(上)...
  5. C语言3D矢量操作有关的功能(附完整源码)
  6. Diango博客--7.自动生成文章摘要
  7. java简化代码的jar_JAVA奇技淫巧简化代码之lombok
  8. Vmware虚拟机修改静态IP无法ping外网,以及eth0不见问题解决
  9. Java ActiveMQ 讲解(二)Spring ActiveMQ整合+注解消息监听
  10. js触发click事件
  11. SQL-55 分页查询employees表,每5行一页,返回第2页的数据
  12. BZOJ5222[Lydsy2017省队十连测] 怪题
  13. 安装java虚拟机_JAVA虚拟机的安装以及JAVA的环境配置
  14. 试验设计第二版茆诗松课后题答案_试验设计习题及答案
  15. 图像处理系列——直方图之直方图规定化(Histogram Specification)
  16. 5.1数学建模与MATLAB--层次分析法(评价类问题)
  17. HTML打地鼠小游戏代码
  18. 至简设计系列_7段数码管显示
  19. android 钢琴识别音阶对错_练习音阶琶音的方法——你确定自己没弄错?
  20. 2022-2028年中国沉香行业发展模式分析及投资趋势预测报告

热门文章

  1. 佳能相机操作 EDSDK 教程 C# 版本
  2. 【Markdown】用 Markdown 代码写出好看的页面
  3. 杂谈:小米是否已经变味?
  4. 以租代购成为企业用车主流
  5. linkin大话设计模式--代理模式
  6. python读ad域日志_基于python LDAP3的AD域账号注册系统
  7. 字节跳动面试,倒在了终面上
  8. EXT各个控件隐藏不可编辑等操作以及一些控件操作
  9. 教你两种方法,轻松锁定数据不被修改
  10. 电脑常死机的状况分析