内联函数

函数的调用,想必大家都用过,一个函数在被另一个函数调用的时候,才有生命,才会为其准备对应的内存空间,再调用完毕之后再清理释放结束。

可以看到,每一次的函数调用都会带来一些时间和空间上的花销。

而自定义函数的一个作用,也是为了提高代码的重用性,可以在需要的时候随时调用,提高开发效率。那么,一个代码本身就不多,又频繁被调用的函数,我们就该好好想想,这样做到底合算不合算了。

好在,C++已经帮我们考虑到这个问题,为我们提供了内联的机制,即仍然使用自定义函数,但在编译的时候,把函数代码插入到函数调用处,从而免去函数调用的一系列过程,像普通顺序执行的代码一样,来解决这个问题!

 

那么用法呢,也非常简单,只需要在函数定义的前面加上关键字inline声明就可以了

#include<iostream>
using namespace std;
  
inline int Max(int a,int b)
{
    return a>b?a:b;
}
int main()
{
    cout<<Max(3,5)<<endl;
    cout<<Max(7,9)<<endl;
    return 0;
}

值得说明的是,内联函数的定义要在调用之前出现,才可以让编译器在编译期间了解上下文,进行代码替换。

除此以外,内联函数与register变量类似,仅仅是我们提给编译器的一个请求,最终是否真正会实现内联,由编译器根据情况自行选择。

 

 

与宏的比较

编辑 语音
通常,在C语言中,内联展开的功能由带参宏(Macros)在源码级实现。内联提供了几个更好的方法:
  • 宏调用并不执行类型检查,甚至连正常参数也不检查,但是函数调用却要检查。
  • C语言的宏使用的是文本替换,可能导致无法预料的后果,因为需要重新计算参数和操作顺序
  • 在宏中的编译错误很难发现,因为它们引用的是扩展的代码,而不是程序员键入的。
  • 许多结构体使用宏或者使用不同的语法来表达很难理解。内联函数使用与普通函数相同的语言,可以随意的内联和不内联。
  • 内联代码的调试信息通常比扩展的宏代码更有用。 [1] 

内联函数的不足

编辑 语音
除了通常使用内联扩展可能带来的问题,作为一种编程语言特性的内联函数也可能并没有看起来那么有效,原因如下:
  • 通常,设计编译器的程序设计者比大多数的程序设计者更清楚对于一个特定的函数是否合适进行内联扩展;一些情况下,对于程序员指定的某些内联函数,编译器可能更倾向于不使用内联甚至根本无法完成内联。
  • 对于一些开发中的函数,它们可能从原来的不适合内联扩展变得适合或者倒过来。尽管内联函数或者非内联函数的转换易于宏的转换,但增加的维护开支还是使得它的优点显得更不突出了。
  • 对于基于C的编译系统,内联函数的使用可能大大增加编译时间,因为每个调用该函数的地方都需要替换成函数体,代码量的增加也同时带来了潜在的编译时间的增加。 [1]

内联函数和宏定义的差别:

内联函数和普通函数相比可以加快程序运行速度,因为不需要中断调用,在编译的时候内联函数可以直接被镶嵌到目标代码中,而宏只是一个简单的替换。 

内联函数需要做参数类型检查,宏不需要

一般内联函数用于以下情况

(1)一个函数被重复不断调用

(2)函数知识简单的几行,且函数内不包含for、while、switch语句。

宏不是函数,只是在编译前(编译预处理阶段)将程序中有关字符串替换成宏体。

 

反之,如果函数体内代码执行的时间要比函数调用的开销大,则不需要使用内联函数,内联函数是以代码膨胀(复制)为代价,将使程序的代码总量增加,消耗更多的内存空间,

因此一般内联函数不用于以下情况

(1)函数体内代码比较长,内联会导致内存空间消耗大

(2)函数体内出现循环,执行函数体内代码时间要比函数调用开销大。

参考:

https://www.dotcpp.com/course/63

posted @ 2021-07-27 10:45  三一一一317  阅读(293)  评论(0)    收藏  举报