大家好,我叫唐亮。
这是EasyC++系列的第31篇文章,我们来谈谈内联函数。
想要追求更好的阅读体验的同学可以点击参观仓库。
内联函数
内联函数是C++中为了提高程序运行效率而设计的。 说实话,我还没有在其他语言中看到过类似的设计。 它与常规函数的主要区别不在于其编写方式,而在于C++编译器将内联函数合并到程序中执行。
要解释这个过程有点复杂,我们需要从编译过程开始。 对于编译型语言来说,编译器所做的就是将人类编写的、人类可以理解的代码翻译成机器可以识别和执行的机器语言,通常是一系列十六进制指令。 然后计算机一步步执行这些指令,完成我们想要的功能。
当我们调用函数时,本质上是指令跳转。 我们首先记录当前运行的指令位置,跳转到函数所在的指令位置执行,执行完成后再跳回来。 除了跳转之外,还会传输和复制一些参数,这需要一定的开销。
内联函数的使用本质上可以理解为使用相应的函数代码而不是函数调用。 可以简单理解为将函数中的代码复制粘贴到函数调用的位置,替换函数跳转。 例如,假设我们有一个计算从坐标到原点的距离的函数:
include<cmath>
double distance(double x, double y) {
return sqrt(x * x + y * y);
}
double x = 3.0, y = 4.0;
double d = distance(x, y);
当我们使用内联函数时,相当于将函数的代码复制粘贴到调用位置:
double x = 3.0, y = 4.0;
double d = sqrt(x * x + y * y);
这就是内联的意义。 使用内联函数后,程序不需要跳转到另一个位置执行,可以节省跳转带来的开销。 因此,它比普通函数运行得更快,但代价是占用更多的内存。 例如,如果我们调用内联函数10次,则相当于十份代码。
内联函数的使用非常简单,只需在函数定义前添加关键字即可。
需要注意的是,有时即使我们添加了关键字,编译器也不一定会遵循它们。 有些编译器会对函数大小有限制,并且会限制内联函数调用自身,即不能递归。
还有一点是,内联函数虽然有内联机制,但是函数的参数仍然是按值传递的,这意味着会发生复制,和普通函数一致。
C语言中没有这个特性。 C语言使用宏定义来实现类似的功能。 但宏定义不是通过参数传递,而是机械替换。
例如:
#define SQUARE(x) x*x
double a = SQUARE(3.4 + 3.5);
这样,我们得到的结果将是3.4 + 3.5 * 3.4 + 3.5,这意味着宏定义只是机械地替换了代码,而不是函数调用。 所以要达到类似函数的效果,可以使用括号:
#define SQUARE(x) ((x) * (x))