内联函数概念
当我们在日常编程的项目中频繁调用一些函数(这些函数一般内部指令都较少)时,程序会反复压栈开销栈空间,为了减少这种开销,内联函数出现了。百度百科词条上如是解释内联函数:
内联函数(有时称作在线函数或编译时期展开函数)是一种编程语言结构,c++中以关键词inline修饰,用来建议编译器对一些特殊函数进行内联扩展(有时称作在线扩展);也就是说建议编译器将指定的函数体插入并取代每一处调用该函数的地方(上下文),从而节省了每次调用函数带来的额外时间开支。 内联函数
理解内联函数
想要理解内联函数是如何作用的,先看如下一段简易的cpp代码:
#include <iostream>
using namespace std;
int Add(int a,int b)
{
return (a + b);
}
int main()
{
int rez1=Add(1, 2);
int rez2=Add(2, 4);
cout << rez1 << " " << rez2 << endl;
return 0;
}
这段代码频繁调用该“较短函数”,在内存中反复压栈开空间,需要使用内联函数,在此之前我们先看一下它的汇编代码:
显然,这里两次出现call Add(?)。
接下来使用内联修饰符再观察:
inline int Add(int a,int b)
{
return (a + b);
}
TIPS1:
要想从这次的汇编代码中获取有用的信息,我们只能在release版本中去查看是否还存在“call Add(?)”。我们知道,调用内联函数后函数将在调用处展开而不是在栈空间压栈。但由于vs2019在release版本中的优化做得很好,我们甚至在汇编中找不到展开的相关信息。
通过百度查询后我发现,debug版本在进行一些配置后也可以看到汇编中的展开信息,操作如下:
右击我们的项目,选中属性:
然后选中“优化”
然后调试起来进入反汇编中查看:
显然这里没有再出现call的指令,而是通过寄存器完成了加法操作,并且每个add函数都如是操作,说明我们的inline起作用了,函数成功被展开。
内联函数必记特点
1.内联函数是经典的空间换时间的做法,当代码指令很多(函数内部达到10行左右的指令就不考虑使用)或是递归都不能使用内联函数。
(在编译的角度理解:假如一个函数编译后内部有10个指令,不使用inline调用100次,那么最后会出现110条指令;而如果使用inline关键字,函数直接展开,最后出现1000条指令)
2.内联函数仅仅是对编译器的建议,并不是说调用了inline,函数就一定会被展开,前提是函数不是递归或者较长函数。
3.在类中定义的函数都是内联函数
4.声明和定义分离的函数不建议使用内联,经常会在链接时出现找不到的错误。因为inline展开函数后函数地址就已经消失不见。
引申C语言
在c++中有内联函数,在c语言中也可以使用宏定义的办法来达到相同的目的,就比如前文举例的简单Add函数,直接写一个宏来实现该函数,通过宏替换也能减少栈开销:
#define ADD(x,y) ((x)+(y))
显然,相比于宏,c++的inline内联使用更加简单不易出错,只需要在函数前加上inline关键字即可,非常好用~