[Effective C++系列]-透彻了解inlining的里里外外
- [原理]
- 可以消除函数调用所带来的开销。
- 编译器最优化机制通常被设计用来浓缩那些“不含函数调用”的代码,因此当你inline某个函数,或许编译器有能力对它(函数本体)执行语境相关最优化。大部分编译器不会为一个“outlined函数调用”执行这种最优化动作。
- 当你申请(隐式或者显式)对一个函数进行inlining时,编译器未必真的这么做了,编译器自己会根据具体情况作出判断。
- 有些你没注意到的写法可能导致一个函数被隐式inlining,例如将函数的声明和实现均放在头文件中。
- [详解]
class person
{
public:
...
int age() {return m_age;} // 该函数会被隐式申请为inline函数
...
private:
int m_age;
};
这样的函数通常是成员函数,但是如果把friend函数的实现也放在头文件内,那么该friend函数也会被隐式申请为inline。
例如:
class dummy
{
public:
explicit dummy(int i) : m_data(i)
{}
private:
int m_data; friend void swap(dummy& lhs, dummy& rhs)
{
int temp = lhs.m_data;
lhs.m_data = rhs.m_data;
rhs.m_data = temp;
}
};
template <typename T>
inline const T& max(const T& a, const T& b)
{return a >b ? a : b;}
inline void fn() {…} // 假设编译器愿意inline“对fn的调用”
void (*pf) () = fn; // pf指向fn
...
fn(); // 该调用会被inlined,因为这是一个正常调用。
pf(); // 该调用不会被inlined, 因为它是通过函数指针实施。
- [总结]
- 一个合乎逻辑的策略是:一开始不要讲任何函数声明为inline,或至少将inlining局限于小型的、被频繁调用的函数身上。这会使得日后的调试和二进制升级更容易,也可使代码膨胀的问题最小化,使程序的速度提升机会最大化。
- 不要只因为function template出现在头文件中,就将它们声明为inline。
- [补充]
From:http://www.cnblogs.com/xkfz007/archive/2012/03/27/2420166.html
不恰当地使用inline导致编译器拒绝进行inlining是会带来副作用的,这会带来代码膨胀(目标码膨胀)和可能极难察觉的bug。因为编译器对普通函数(没有声明为inline)的实现与对inlining失败的函数的实现是不同的。
普通函数在编译时被单独编译为一个对象,包含在相应的目标文件中。目标文件在链接时,对该函数的调用会被链接到该对象上。
若一个函数被声明为inline,那么编译器即使遇到该函数的声明也不会为该函数编译一个对象,因为inline函数是在调用的地方进行展开的。但是如果在调用的地方发现该inline函数不适合被展开怎么办?一种做法是在调用该内联函数的目标文件中为该内联函数编译一个对象。这么做的直接后果是:若在多个文件调用了内联失败的函数,其中每个文件对应的目标文件中都会包含一份该内联函数的目标代码。
如果编译器真的选择了上面的做法对待内联失败的函数,那么目标代码的体积膨胀得与成功内联的目标代码一样,但目标代码的效率确和没内联一样。
更糟的是由于存在多份函数目标代码带来一些程序bug。最明显的例子是:内联失败的函数内的静态变量实际上就不在只有一份,而是有若干份。这显然是个错误,但是如果不了解内幕就很难找到原因。
[Effective C++系列]-透彻了解inlining的里里外外的更多相关文章
- [Effective C++ --030]透彻了解inlining的里里外外
引言 inline函数 在函数声明或定义中函数返回类型前加上关键字inline即把min()指定为内联. inline函数对编译器而言必须是可见的,以便它能够在调用点内展开该函数.与非inline函 ...
- Effective C++ -----条款30:透彻了解inlining的里里外外
将大多数inlining限制在小型.被频繁调用的函数身上.这可使日后的调试过程和二进制升级(binary upgradability)更容易,也可使潜在的代码膨胀问题最小化,使程序的速度提升机会最大化 ...
- 【30】透彻了解inlining 的里里外外
1.inline方法相当于文本替换,不需要承担方法调用的额外开销,同时还有潜在的优势,文本替换后,编译器会进行代码优化.而对于方法调用,编译器没有能力进行代码优化. 2.显而易见,inline方法往往 ...
- 条款30:透彻了解inline的里里外外(understand the ins and outs of inlining)
NOTE: 1.将大多数inline限制在小型 被频繁调用的函数身上.这可使日后的调试过程和二进制升级(binary upgradability)更容易,也可使潜在的代码膨胀问题最小化, 使程序的速度 ...
- Effective java 系列之避免过度同步和不要使用原生态类型,优先考虑泛型
避免过度同步(67):在一个被同步的方法或代码块中,不要调用哪些被设计成被覆盖的方法或者是由客户端以函数对象的形式提供的方法(21). 有点拗口,书上提供的创建者与观察者模式,add方法太多,看得眼花 ...
- [Effective C++系列]-为多态基类声明Virtual析构函数
Declare destructors virtual in polymorphic base classes. [原理] C++指出,当derived class对象经由一个由base clas ...
- Effective java 系列之异常转译
异常转译:当位于最上层的子系统不需要关心底层的异常细节时,常见的作法时捕获原始异常,把它转换一个新的不同类型的异常,在将新异常抛出. 通常方法捕获底层异常,然后抛高层异常. public static ...
- Effective java 系列之更优雅的关闭资源-try-with-resources
背景: 在Java编程过程中,如果打开了外部资源(文件.数据库连接.网络连接等),我们必须在这些外部资源使用完毕后,手动关闭它们.因为外部资源不由JVM管理,无法享用JVM的垃圾回收机制,如果我们不在 ...
- 条款30:透彻了解inline的里里外外。
inline可以带来各种好处: 首先其可以使得消除函数调用带来的开销,再者编译器对这种非函数的代码可以做出更多的优化策略. 但是inline函数首先肯定是会导致程序代码的大小更加的庞大,这样会带来 ...
随机推荐
- Intent中的重要属性详解
Intent中的四个重要属性主要有四个,分别是Action.Data.Category.Extras. Intent作为联系各Activity,BroadcaseReciver,Service之间的纽 ...
- React-Native个人信息界面
最近在做一个小练习项目,用户登陆后需要跳转到用户登录信息界面,加班半个小时终于将界面的布局搞定.接触Rect-Native也有一段时间了,以前没有做过ios,只做过android,就布局和开发效率上来 ...
- python 3.5 之 单双三引号
1. 单引号和双引号用法都是一样的,但是如果字符串里有相同的字符时要使用\进行转义 举例:1) print 'hello'2) print "hello"1和2,结果都是hello ...
- Activiti+oracle 启动项目时不能自动建表或更新表的问题分析及解决办法
现象描述:按照正常配置,第一次启动时不能自动建表 关键配置片段如下: <bean id="processEngineConfiguration" class="or ...
- source install MacPorts--checking for Tcl configuration... configure: error: Can't find Tcl configuration definitions
If you installed MacPorts using the package installer, skip this section. To install MacPorts from t ...
- c++大数模版
http://blog.csdn.net/hackbuteer1/article/details/6595881 #include<iostream> #include<string ...
- 九章算法系列(#4 Dynamic Programming)-课堂笔记
前言 时隔这么久才发了这篇早在三周前就应该发出来的课堂笔记,由于懒癌犯了,加上各种原因,实在是应该反思.好多课堂上老师说的重要的东西可能细节上有一些急记不住了,但是幸好做了一些笔记,还能够让自己回想起 ...
- 使用TypeScript开发一个在线记事本,支持离线存储
先贴上源码传送门: https://github.com/flowforever/yaryin.note 记事本网址: http://yindoc.com , 井号后面写你喜欢的文件名即可. 最近在研 ...
- Inno Setup 插件 CallbackCtrl V1.1 (回调函数插件)
原文 http://restools.hanzify.org/article.asp?id=101 VC 重现 InnoCallback 的功能. Version 1.1修正在某些 Windows 平 ...
- 在MFC下实现图像放大镜
当我们想仔细观察某个细微的东西时,一般都会使用放大镜.而要看清显示在计算机屏幕上的图片或文字时通常也可以借助于Windows操作系统附带的放大程序来实现.但该程序只能以固定的放大倍数去进行观看,有时并 ...