为什么C++要引入内联函数?
频繁消耗栈帧的函数
栈帧的简单介绍:
当某个函数运行时,机器需要分配一定的内存去进行函数内的各种操作,这个过程中分配的那部分栈称为栈帧。下图描述了栈帧的通用结构。栈帧是一段有界限的内存区间,由最顶端的两个指针界定,寄存器%ebp为基址指针寄存器(extended base pointer),而寄存器%esp为栈指针寄存器(extended stack pointer)(也就是说寄存器%ebp保存了所分配内存的最高地址,寄存器%esp保存了所分配内存的最低地址)。当程序执行时,栈指针(栈顶)可以移动,因此大多数信息的访问都是相对于桢指针的。
也就是说,每当我们在C语言中调用函数时,栈上都需要开辟一定空间供我们使用,从汇编代码的角度来看,如果是重复进行大量的函数压栈操作,对于栈上空间的消耗是巨大的,极易导致栈溢出现象发生,进而导致程序崩溃,因此我们需要一些解决方法来防止这样的错误产生.
极易出错的宏替换
在C语言中,为了解决类似的问题,我们学习了使用类函数宏来替换这些大量重复使用但又并不复杂的函数,如,将求两数中的最大值的函数改写为类函数宏:
#define X 3 #define Y 5 #define MAX(X,Y) X>Y?X:Y int main() { printf("%d", MAX(X, Y)); return 0; }
但宏替换并不是一个很好的解决方案,因为它简单粗暴的替换逻辑非常容易导致出错,如:
以及其他相关的问题,具体可以查看这篇博客的第四部分:宏定义陷阱,这里就不一一赘述了.【C语言】什么是宏定义?(#define详解)
内联函数的概念
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数提升程序运行的效率。
如下函数Max,只需要在正常函数前加上关键字inline就可以使其称为内联函数:
inline int Max(int x, int y) { return x > y ? x : y; } int main() { int max=Max(3, 5); return 0; }
内联函数的特性
- inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。
- inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。下图为《C++prime》第五版关于inline的建议:
- inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。如:
- 注:默认debug版本下内联不会起作用,否则就无法调试了。
结语
希望这篇关于内联函数的博客能对大家有所帮助,欢迎大佬们留言或私信与我交流.
学海漫浩浩,我亦苦作舟!关注我,大家一起学习,一起进步!
相关文章推荐