C++对C语言的扩展--内联函数
1 inline内联函数
c 语言中有宏函数的概念。宏函数的特点是内嵌到调用代码中去,避免了函数调用的开销。但是由于宏函数的处理发生在预处理阶段,缺失了语法检测和有可能带来的语意差错。
1.1 内联函数基本概念
C++提供了 inline 关键字,实现了真正的内嵌。
#include <iostream>
using namespace std;
inline void func(int a)
{
a = 20;
cout << a << endl;
}
int main()
{
func(10);
// 编译器将内联函数的函数体直接展开
// 相当于
/*
{
a = 10;
cout << a << endkl;
}
*/
return 0;
}
特点:
- 内联函数声明时inline关键字必须和函数定义结合在一起,否则编译器会直接忽略内联请求。(函数声明和实现同时加上关键字 inline 才称为内联)
- C++编译器直接将函数体插入在函数调用的地方。
- 内联函数没有普通函数调用时的额外开销(压栈,跳转,返回)。
- 内联函数是一种特殊的函数,具有普通函数的特征(参数检查,返回类型等)
- 内联函数由编译器处理,直接将编译后的函数体插入调用的地方;
宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程。 - C++中内联编译的限制:
1 不能存在任何形式的循环语句
2 不能存在过多的条件判断语句
3 函数体不能过于庞大
4 不能对函数进行取址操作
5 函数内联声明必须在调用语句之前、 - 编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。因此, 当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。
- 类的成员函数前都隐式的加了关键字 inline
1.2 内联函数 vs 宏函数
#include <iostream>
#include <string.h>
using namespace std;
#if 0
优点:内嵌代码,避免压栈与出栈带来的开销
缺点:代码替换,易使生成代码体积变大,易产生逻辑错误。
#endif
#define SQR(x) ((x)*(x))
#if 0
优点:高度抽象,避免重复开发
缺点:压栈与出栈,带来开销
#endif
int main()
{
int i = 0;
while (i < 5)
{
//printf("%d\n", SQR(i++));
printf("%d\n", sqr(i++));
}
return 0;
}
宏函数缺陷:
- 必须要加上括号保证完整性
- 即使加上括号,有些运算任然与预期结果不符
1.3 内联函数总结
- 优点:避免调用时的额外开销(入栈与出栈操作)
- 代价:由于内联函数的函数体在代码段中会出现多个“副本”,因此会增加代码段的空间。
- 本质:以牺牲代码段空间为代价,提高程序的运行时间的效率。
- 适用场景:函数体很“小”,且被“频繁”调用。
内联函数只是给编译器一个建议,但编译器不一定接受这个建议,好的编译器会自己给短小的函数前加上关键字inline