inline 函数的基本应用讨论
1 inline 函数的定义
一般来说,内联机制适用于优化小的、只有几行的而且经常被调用的函数。
什么情况下编译器有可能会真正让你的函数成为内联呢?
(1) 函数显式声明为 inline;
(2) 函数定义在 class 定义内部;
呃,原则上 inline 函数只能定义在头文件中,虽然定义在 class 内部的也是 inline 函数,而 class 却也可以定义在 cpp 文件中……
inline 函数体有个条件最好要满足:函数体非常简单,比如只有一个 renturn 语句。不过即使这个条件满足了,这个函数最终如何实现,会不会真正的内联,仍然取决于编译器。
2 使用 inline 取代宏
C 语言中的宏有时候是个比较好用的东西, 但在 C++中不推荐使用预处理功能, 宏, 在 C++中都可以找到对应的替代物.比如下面的例子.
计算两个对象的最大值:
这个语句有很多缺陷,想想都让人头疼。象这样的宏,你必须记住对每个参数都要加上括号;否则,别人调用你的宏时如果用了表达式,就会造成很大的麻烦。但是即使你加了括号,还会有象下面这样奇怪的事发生:
这种情况下,max 内部发生些什么,取决于它比较的是什么值!这样的代码大家应该趁早敬而远之。
幸运的是你不必再忍受这样愚笨的语句了。内联函数可以用普通函数实现宏的效率,再加上可预计的行为和类型安全:
inline int max(int a, int b){return a > b ? a : b; }
这个函数可没有什么奇怪的事情发生了。(1)函数会对参数进行类型检查;(2)函数的参数不会对其调用时传入的表达式重复计算。
这个版本的 max 只能处理 int 类型。我们把这个话题再延伸一下, 使用模板可以很轻巧地解决这个问题:
这个模板产生了一整套函数,每个函数拿两个可以转换成同种类型的对象进行比较,然后返回较大的(常量)对象的引用。因为不知道 T 的类型,返回时传递引用可以提高效率。不要奇怪,模板函数也可以定义为 inline,注意一下其定义的语法形式,inline 关键字放在 template 之后,函数返回值之前。
内联函数的基本思想是将每个函数调用,用它的代码体来替换,这样一来,内联函数看起来像函数,运行起来也像函数,但使用时无需承担函数调用的开销。不要小看 inline 函数的优势,它具有和宏一样的效率,但是 #define 的宏展开,只是单纯的代码字符串替换,而 inline 函数是可以检查你传入的参数的。
当然凡事没有绝对。内联函数如果调用的地方太多,或者其本身函数体的代码过多,可能会增加整个目标代码的体积。而且更重要的是,inline 这个指令,它只是给编译器的一种提示,编译器不一定必须这么做,当内联函数包含循环和递归等比较复杂的代码时,编译器八成会忽略掉 inline,更不用提虚函数了。所以这个语言特性是依赖于编译器的,使用的时候就需要特别注意了。
3 inline 在函数对象中的应用
函数对象,本来是由重载了函数调用操作符 operator()而衍生出来的概念,但是函数对象在 C++中的应用却非常广泛,对 C++程序设计思想的贡献非同小可。
如果一个类的对象具有 operator()运算符,这个对象活动起来就像函数,我们就称它为一个函数对象,它可以像一个函数一样使用。有的书中称这种函数形式为仿函数。
例如这个 Add 类:
将它用到加法运算中,和调用函数的效果是一样的。例如:
由于 operator()这个函数一般情况下也相当的短小精悍,且其定义也位于 class 内部,所以可以认为它也是 inline 函数,编译器会实现为内联调用,在性能方面甚至高于普通的函数调用。
版权声明: 本文为 InfoQ 作者【老王同学】的原创文章。
原文链接:【http://xie.infoq.cn/article/6d21660e9ea75828483e7f5e7】。文章转载请联系作者。
评论