内联函数【C++】
简介
内联函数是一种用于编译时的技术,编译器一般会对声明为内联函数的函数进行内联扩展也可以称作在线扩展,编译器会将指定的内联函数体插入到每一处调用该函数的位置,可以节省每次函数调用带来的的额外时间成本和空间成本。但同时内联函数会耗费更多的存储资源,是一种典型的用时间换空间的方式,所以是否使用内联函数需要基于存储资源以及性能要求进行对应的权衡。
原理
C++中函数调用的过程包含以下流程:
函数被调用需要将被调用函数的参数进行压入堆栈的操作。参数入栈顺序需要符合函数的调用约定,参数一般都是按照从左往右的顺序入栈。
函数结束代码要返回到调用函数继续执行,所以在执行函数调用时,会自动将调用者(Caller)的下一条指令地址压入堆栈,函数结束时,从堆栈读取这个地址,跳转到该地址指向的指令继续执行。
返回地址入栈之后,就可以跳转到被调用函数的代码区进行执行。至此之后的栈帧的都是由被调用方(Callee)来构建。之前的栈帧属于调用方。
在Callee开始执行之前首先将EBP寄存器的值压入堆栈。此时EBP寄存器的值还是用于Caller函数的,EBP寄存器的地址用来访问Caller函数的参数和局部变量,因此需要将它暂存在堆栈中,Callee函数退出时恢复Caller执行时用于恢复该值。EBP的旧值存入堆栈的同时给EBP赋于新值即ESP的值 。
Callee函数为局部变量分配地址。局部变量入栈是将ESP减去某个值,直接为局部变量分配空间。
函数中使用到的通用寄存器的值也需要执行入栈操作进行暂存以便函数结束时恢复。通用寄存器包括EBX,ESI,EDI等。
以上流程就是函数调用过程中建立栈帧的开销,而内联函数通过消除函数调用可以提升如下性能:
消除了函数调用过程中的各种指令,包括在堆栈或寄存器中存储参数指令,调用函数指令,返回函数过程,获取返回值,从堆栈中删除参数并恢复寄存器等的指令。
内联函数直接通过引用进行传递参数,减少了传递引用,也减少了寄存器的使用,减少了参数的存储以及恢复等成本。