内联函数
概念
以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,内联函数能提升程序运行的效率。对比于传统的函数调用,内联函数更像宏。告诉编译器在调用函数时将函数的代码插入到调用处,从而减少函数跳转、维护函数栈帧等操作所花费的时间,但是由于所有调用内联函数处都要将其展开,这样会耗费一定的空间。所以,内联函数实际上是一种用空间换时间的做法。
观察以下代码中的函数调用
现在我们用inline修饰add函数再观察其函数在底层是如何调用的。
我们发现,在调用add()时并没有call指令,也就意味着没有函数跳转,进而证实了,用inline装修的函数直接展开计算。
如何查看到编译器对内联函数的处理呢?
1. 在release模式下,查看编译器生成的汇编代码中是否存在call Add
2. 在debug模式下,需要对编译器进行设置,否则不会展开(因为debug模式下,编译器默认不会对代码进行优化)
步骤:
内联函数特性
1. inline是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会用函数体替换函数调用,缺陷:可能会使目标文件变大,优势:少了调用开销,提高程序运行效率。2. inline对于编译器而言只是一个建议,不同编译器关于inline实现机制可能不同,一般建议:将函数规模较小(即函数不是很长,具体没有准确的说法,取决于编译器内部实现)、不是递归、且频繁调用的函数采用inline修饰,否则编译器会忽略inline特性。
3. inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址
了,链接就会找不到(只在当前文件内生效).
面试题
宏的优缺点:
优点:
1.增强代码的复用性。
2.提高性能。
缺点:
1.不方便调试宏。(因为预编译阶段进行了替换)
2.导致代码可读性差,可维护性差,容易误用。
3.没有类型安全的检查 。
C++有哪些技术替代宏?
1. 常量定义 换用const enum
2. 短小函数定义 换用内联函数
inline和宏的使用场景?
内联函数:
使用场景:
3.提高性能: 在一些性能敏感的场景中,通过内联函数可以减少函数调用带来的额外开销。
- 适用于中小规模的函数: 内联函数通常适用于函数体较小的情况,这样可以避免函数调用的开销。
- 频繁调用的函数: 内联函数对于频繁调用的函数比较有效,因为避免了函数调用的开销。
区别:
- 类型检查: 内联函数进行了类型检查,而且它是真正的函数,因此具有类型安全性。
- 符号表: 内联函数有自己的符号表,可以提供更好的封装和作用域。
宏:
使用场景:
- 简单而短小的代码: 宏通常用于定义简单而短小的代码块。
- 代码生成: 用于在预处理阶段生成代码,可以通过宏来实现代码的重复或模板化。
区别:
- 类型检查: 宏在预处理阶段进行文本替换,没有类型检查,可能导致一些不容易察觉的错误。
- 作用域: 宏没有自己的作用域,是简单的文本替换,可能导致一些命名冲突或意外的替换。
共同点:
- 性能优化: 都是为了提高代码执行效率而设计的工具。
- 代码体积增加: 过度使用内联函数或宏都可能导致代码体积增加,对缓存不友好,反而影响性能。