目录
一、什么是内联函数
二、内联函数的弊端
1.造成系统颠簸
2.对于编译器
三、明智的使用内联函数
一、什么是内联函数
首先做一下简单的介绍:内联函数的基本思想在于将每个函数调用以它的代码体来替换。通俗来讲,就是在函数调用的地方,将函数代码按照逻辑展开 。
关于函数调用产生的过程:
先传参 将下一行指令地址入栈——保护现场 将ebp寄存器入栈 用esp? ebp进行偏移——开辟栈帧 执行函数体 返回值 栈帧回退 恢复现场 参数清除
内联函数的优点就在于他对于省略其他步骤,在展开后之直接执行函数体,避免大量时间消耗和内存占用 。
关于按逻辑展开的具体解释可参考上一篇:https://blog.csdn.net/Justina0806/article/details/121637840?spm=1001.2014.3001.5501
二、内联函数的弊端
1.造成系统颠簸
但我们很快就会意识到,展开的这种形式很可能会增加整个目标代码的体积。在一台内存有限的计算机里,过分地使用内联所产生的程序会因为有太大的体积而导致可用空间不够。即使可以使用虚拟内存,内联造成的代码膨胀也可能会导致系统颠簸,你的程序运行时就会慢得像在爬。
系统颠簸是指在虚拟存储器中,刚从主存中换出的页面序列,很快又被调入的页面序列反复调进调出的现象
但从另一方面看,如果内联函数体非常短,编译器为这个函数体生成的代码就会真的比为函数调用生成的代码要小许多。如果是这种情况,内联这个函数将会确实带来更小的目标代码和更高的缓存命中率!
2.对于编译器
inline指令就象register,对于编译器只是一种提示而非命令。也就是说,只要编译器愿意,它就可以随意地忽略掉你的指令,事实上编译器常常会这么做。
上文的关键字regiter:是指请求编译器尽可能的将变量存在CPU的寄存器中
例如,大多数编译器拒绝内联"复杂"的函数。例如,包含递归的函数,还有,虚函数调用。
分别来解释一下。对于递归函数,递归函数中存在嵌套,递归的结束是有一个变量作为终止条件的,当变量到达某个值的时候停止,而内联函数的展开是在编译时期,我们是无法取到变量的值,就无法作为判断终止条件,那么内联函数就会被无限的展开。
对于虚函数:virtual本身就指"等到运行时再决定调用这个函数",而inline的意思是"在编译期间将调用之处用被调函数来代替",这就使得编译器甚至还不知道哪个函数将被调用,所以虚函数就理所当然的被编译器拒绝作为内联函数。
三、明智的使用内联函数
所以说,明智的使用内联函数才能起到优化代码的作用。
“一个程序往往花80%的时间来执行程序中20%的代码“”。这是一条很重要的定律,因为它提醒你,作为程序员的一个很重要的目标,就是找出这20%能够真正提高整个程序性能的代码。
|