读书笔记_Effective_C++_条款三十:了解inline的里里外外
学过基本程序课的同学都知道,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的里里外外的更多相关文章
- 读书笔记_Effective_C++_条款三十九:明智而审慎地使用private继承
private继承的意义在于“be implemented in turns of”,这个与上一条款中说的复合模型的第二层含义是相同的,这也意味着通常我们可以在这两种设计方法之间转换,但书上还是更提倡 ...
- 读书笔记_Effective_C++_条款三十四:区分接口继承和实现继承
这个条款书上内容说的篇幅比较多,但其实思想并不复杂.只要能理解三句话即可,第一句话是:纯虚函数只继承接口:第二句话是:虚函数既继承接口,也提供了一份默认实现:第三句话是:普通函数既继承接口,也强制继承 ...
- 读书笔记_Effective_C++_条款三十二:确定你的public继承继承塑模出is-a关系
这一条款是说的是公有继承的逻辑,如果使用继承,而且继承是公有继承的话,一定要确保子类是一种父类(is-a关系).这种逻辑可能与生活中的常理不相符,比如企鹅是生蛋的,所有企鹅是鸟类的一种,直观来看,我们 ...
- 读书笔记_Effective_C++_条款三十六:绝不重新定义继承而来的non-virtual函数
这个条款的内容很简单,见下面的示例: class BaseClass { public: void NonVirtualFunction() { cout << "BaseCla ...
- 读书笔记_Effective_C++_条款三十八:通过复合塑模出has-a或者is-implemented-in-terms-of
如果说public是一种is-a的关系的话,那么复合就是has-a的关系.直观来说,复合就是在一个类中采用其他类的对象作为自身的成员变量,可以举个例子,像下面这样: class Person { pr ...
- 读书笔记_Effective_C++_条款三十五:考虑virtual函数以外的其他选择
举书上的例子,考虑一个virtual函数的应用实例: class GameCharacter { private: int BaseHealth; public: virtual int GetHea ...
- 读书笔记_Effective_C++_条款二十九:为“异常安全”而努力是值得的
还是举书上的例子: void PrettyMenu::changeBackground(std::istream& imgSrc) { lock(&mutex); delete bgI ...
- 读书笔记_Effective_C++_条款四十九:了解new_handler的行为
本章开始讨论内存分配的一些用法,C/C++内存分配采用new和delete.在new申请内存时,可能会遇到的一种情况就是,内存不够了,这时候会抛出out of memory的异常.有的时候,我们希望能 ...
- 读书笔记_Effective_C++_条款四十八:了解模板元编程
作为模板部分的结束节,本条款谈到了模板元编程,元编程本质上就是将运行期的代价转移到编译期,它利用template编译生成C++源码,举下面阶乘例子: template <int N> st ...
随机推荐
- webconfig的配置解析
<?xml version="1.0"?> <!--注意: 除了手动编辑此文件以外,您还可以使用 Web 管理工具来配置应用程序的设置.可以使用 Visual S ...
- 前端nginx时,让后端tomcat记录真实IP【转】
对于nginx+tomcat这种架构,如果后端tomcat配置保持默认,那么tomcat的访问日志里,记录的就是前端nginx的IP地址,而不是真实的访问IP.因此,需要对nginx.tomcat做如 ...
- android sdcard 权限管理策略研究
自从android4.4 以来,第三方应用程序是不能再随便的访问sdcard了,从开发者的角度而言,研究一下android系统到底是怎么样来实现这样的控制还是比较有价值的. 首先分析下现状,现在已知, ...
- Python股票信息抓取(三)
最近在看mongodb,然后会用了一些最简单的mongodb的操作,然后想着结合股票信息的数据的抓取,然后将数据存储在mongodb中,对于mongo和数据库的最大的区别是,mongo不需要建表,直接 ...
- covariance matrix 和数据分布情况估计
how to get data covariance matrix: http://stattrek.com/matrix-algebra/covariance-matrix.aspx meaning ...
- 洛谷P1008三连击 题解
题目传送门 使用dfs搜索,搜索9个数字,注意回溯...最后判断是否符合条件,输出. #include<bits/stdc++.h> using namespace std; ],a[]; ...
- jmeter----计数器
在测试过程中,往往需要一些有一定规则的数字,这个时候,可以使用配置元件中的计数器去实现. 一.界面显示 二.配置说明 1.名称:标识 2.注释:备注 3.启动:是指计数器开始的值 4.递增:每次增加的 ...
- [实战]MVC5+EF6+MySql企业网盘实战(18)——文件上传,下载,修改
写在前面 经过一段时间的秀秀改改,终于把文件上传下载,修改文件夹文件名称的功能实现了. 系列文章 [EF]vs15+ef6+mysql code first方式 [实战]MVC5+EF6+MySql企 ...
- CentOS下Redis安装与配置
本文详细介绍redis单机单实例安装与配置,服务及开机自启动.如有不对的地方,欢迎大家拍砖o(∩_∩)o (以下配置基于CentOS release 6.5 Final, redis版本3.0.2 [ ...
- ubuntu下 pycharm使用andcoda下的tensorflow
在ubuntu中 tensorflow是安装在andconda里的一个虚拟环境中,他就相当于一个容器,将tensorflow的整个环境去模拟隔离出来,因为我们直接使用andconda库去作为pycha ...