学过基本程序课的同学都知道,inline是内联的关键字,它可以建议编译器将函数的每一个调用都用函数本体替换。这是一种以空间换时间的做法。把每一次调用都用本体替换,无疑会使代码膨胀,但可以节省函数调用的成本,因为函数调用需要将之前的参数以堆栈的形式保存起来,调用结束后又要从堆栈中恢复那些参数。

但注意inline只是对编译器的一个建议,编译器并不表示一定会采纳,比如当一个函数内部包含对自身的递归调用时,inline就会被编译器所忽略。对于虚函数的inline,编译器也会将之忽略掉,因为内联(代码展开)发生在编译期,而虚函数的行为是在运行期决定的,所以编译器忽略掉对虚函数的inline。对于函数指针,当一个函数指针指向一个inline函数的时候,通过函数指针的调用也有可能不会被编译器处理成内联。

另一方面,即使有些函数没有inline关键字,编译器也会将之内联,用本体替换调用代码,比如直接写在class内部的成员函数,如下:

 class Person
{
private:
int age;
public:
int getAge() const
{
return age;
}
void setAge(const int o_age);
};
void Person::setAge(const int o_age)
{
age = o_age;
}

这里getAge()尽管没有inline关键字,但因为是直接写在class里面的,所以编译器将之处理成内联的;setAge()是在类内声明、类外定义的,编译器就不会将之处理成内联的了。

构造函数和析构函数虽然“看”似简单,但编译器会在背后做很多事情,比如一个空的构造函数里面会由编译器写上对所有成员函数的初始化,如果将之inline,将会导致大批量的代码复制,所以不对构造函数和析构函数inline为好。

要慎用inline,是因为一旦编译器真的将之inline了,那么这个inline函数一旦被修改,整个程序都需要重新编译,而如果这个函数不是inline的,那么只要重新连接就好。另外,一些调试器对inline函数的支持也是有限的。

作者认为,“一开始先不要将任何函数声明为inline”,经测试,确实发现某个函数的inline要比不对之inline的性能提升很多,才对之inline。在大多数情况下,inline并不是程序的瓶颈,真正的精力应该放在改善一些算法的修缮,以及反复调用的代码研究上,它们往往才是耗时的瓶颈所在。

最后总结一下:

1. 将大多数inlining限制在小型、被频繁调用的函数身上

2. 不要只因为function templates出现在头文件,就将它们声明为inline(这个内容知道就行了,我在读书笔记的正文中没有说)

读书笔记_Effective_C++_条款三十:了解inline的里里外外的更多相关文章

  1. 读书笔记_Effective_C++_条款三十九:明智而审慎地使用private继承

    private继承的意义在于“be implemented in turns of”,这个与上一条款中说的复合模型的第二层含义是相同的,这也意味着通常我们可以在这两种设计方法之间转换,但书上还是更提倡 ...

  2. 读书笔记_Effective_C++_条款三十四:区分接口继承和实现继承

    这个条款书上内容说的篇幅比较多,但其实思想并不复杂.只要能理解三句话即可,第一句话是:纯虚函数只继承接口:第二句话是:虚函数既继承接口,也提供了一份默认实现:第三句话是:普通函数既继承接口,也强制继承 ...

  3. 读书笔记_Effective_C++_条款三十二:确定你的public继承继承塑模出is-a关系

    这一条款是说的是公有继承的逻辑,如果使用继承,而且继承是公有继承的话,一定要确保子类是一种父类(is-a关系).这种逻辑可能与生活中的常理不相符,比如企鹅是生蛋的,所有企鹅是鸟类的一种,直观来看,我们 ...

  4. 读书笔记_Effective_C++_条款三十六:绝不重新定义继承而来的non-virtual函数

    这个条款的内容很简单,见下面的示例: class BaseClass { public: void NonVirtualFunction() { cout << "BaseCla ...

  5. 读书笔记_Effective_C++_条款三十八:通过复合塑模出has-a或者is-implemented-in-terms-of

    如果说public是一种is-a的关系的话,那么复合就是has-a的关系.直观来说,复合就是在一个类中采用其他类的对象作为自身的成员变量,可以举个例子,像下面这样: class Person { pr ...

  6. 读书笔记_Effective_C++_条款三十五:考虑virtual函数以外的其他选择

    举书上的例子,考虑一个virtual函数的应用实例: class GameCharacter { private: int BaseHealth; public: virtual int GetHea ...

  7. 读书笔记_Effective_C++_条款二十九:为“异常安全”而努力是值得的

    还是举书上的例子: void PrettyMenu::changeBackground(std::istream& imgSrc) { lock(&mutex); delete bgI ...

  8. 读书笔记_Effective_C++_条款四十九:了解new_handler的行为

    本章开始讨论内存分配的一些用法,C/C++内存分配采用new和delete.在new申请内存时,可能会遇到的一种情况就是,内存不够了,这时候会抛出out of memory的异常.有的时候,我们希望能 ...

  9. 读书笔记_Effective_C++_条款四十八:了解模板元编程

    作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...

随机推荐

  1. go 数据变量和操作符

    数据类型 布尔类型 a. var b bool 和 var b bool = true 和 var b = falseb. 操作符 == 和 !=c. 取反操作符: !bd. && 和 ...

  2. linux下C语言实现的内存池【转】

    转自:http://blog.chinaunix.net/uid-28458801-id-4254501.html 操作系统:ubuntu10.04 前言:     在通信过程中,无法知道将会接收到的 ...

  3. opencv配置过程 (cmake,vs2013,qt 5.4)

    平台及软件: Windows 7 X86 Visual Studio 2013 OpenCV3.0.0 Cmake3.3 1.下载Windows下的安装文件OpenCV-3.0.0.exe,解压,选择 ...

  4. .htaccess技巧: URL重写(Rewrite)与重定向(Redirect)

    URL重定向是.htaccess的重头戏,它可以将长地址转为短地址.将动态地址转为静态地址.重定向丢失的页面.防止盗链.实现自动语言转换等.笔者觉得难点是在正则表达式的运用和理解上. 实现所有这些神奇 ...

  5. 前端html第三方登录集合,微信,微博,QQ

    申请开发者账号之内的就不累赘了,网上一大堆: 说下需求,一个网页要在三类容器运行,公司app,微信自动登录,浏览器. 假设是已经申请完成各平台开发者账号. 先来简单的,微博和QQ 微博: 引入微博JS ...

  6. LightOJ 1369 Answering Queries(找规律)

    题目链接:https://vjudge.net/contest/28079#problem/P 题目大意:给你数组A[]以及如下所示的函数f: long long f( int A[], int n  ...

  7. Linux文件访问和日志

    一.文件系统创建一个文件的过程假设我们想要新增一个文件,此时文件系统的行为是:先确定用户对于欲新增文件的目录是否具有 w 与 x 的权限,若有的话才能新增:根据 inode bitmap 找到没有使用 ...

  8. C++ 四种显示转换

    转自:http://www.jellythink.com/archives/205   (果冻想) 前言 这篇文章总结的是C++中的类型转换,这些小的知识点,有的时候,自己不是很注意,但是在实际开发中 ...

  9. luoguP3317 [SDOI2014]重建 变元矩阵树定理 + 概率

    首先,我们需要求的是 $$\sum\limits_{Tree} \prod\limits_{E \in Tree} E(u, v) \prod\limits_{E \notin Tree} (1 - ...

  10. POJ2157 Check the difficulty of problems 概率DP

    http://poj.org/problem?id=2151   题意 :t个队伍m道题,i队写对j题的概率为pij.冠军是解题数超过n的解题数最多的队伍之一,求满足有冠军且其他队伍解题数都大于等于1 ...