C++内联函数inline
1.inline函数
当程序执行函数调用时,系统要建立栈空间,保护现场,传递参数以及控制程序执行的转移等等,这些工作需要系统时间和空间的开销。
请看如下程序,读入一行字符,逐个判断是否为数字字符:
#include<iostream>
#include<assert.h>
using namespace std;
bool IsNumber(char ch)
{
return ch >= '0' && ch <= '9' ? true : false;
}
int main()
{
char ch;
//while(cin(ch)),ch!='\n')\\读取字符时并不把\n读取到ch里面,由于该循环遇到\n才结束,因此回成死循环
while (cin.get(ch), ch != '\n')//读取字符时无论输入什么都读取进去,包括\n
{
if (IsNumber(ch))
{
cout << "是数字字符" << endl;
}
else
{
cout << "不是数字字符" << endl;
}
}
return 0;
}
当函数功能简单,使用频率很高,为了提高效率,直接将函数的代码嵌入到程序中。但这个办法有缺点,一是相同代码重复书写,二是程序可读性没有使用函数好。
为了协调好效率和可读性之间的矛盾,C++提供了另一种方法,即定义内联函数,方法是在定义函数时用修饰词inline。
inline bool IsNumber(char ch)
{
return ch>='0'&&ch<='9'?true:false;
}
加inline关键字将其改为内联函数,在编译期间编译器能够在调用点内联展开该函数。(不需要进行现场的保护和恢复)
实例:在debug模式下,设置编译器。
总结:
inline是一种以空间换时间的做法,省去调用函数开销。但当函数体的代码过长或者是递归函数即便加上inline关键字,也不会在调用点以内展开该函数。
如果函数的执行开销小于开栈清栈的开销(函数体较小),函数不要是递归函数使用inline处理效率高;
如果函数的执行开销大于开栈清栈的开销,使用普通函数处理效率高。
inline对于编译器而言只是一个建议,最终是否实现inline取决于编译器,编译器会自动优化。
inline不建议声明和定义分离,分离会导致链接错误。因为inline被展开,就没有函数地址了,链接就会找不到。(链接时报错)
2.宏和内联函数的区别
#include<iostream>
using namespace std;
#define Max(a,b) ((a)>(b)?(a):(b))
inline int max(int a,int b)
{
return a>b?a:b;
}
- 宏定义不是函数,但是使用起来像函数。预处理器用复制宏代码的方式代替函数的调用,省去了函数压栈退栈过程,提高了效率;
内联函数本质上是一个函数,内联函数一般用于函数体的代码比较简单的函数,不能包含复杂的控制语句,while、switch,并且内联函数本身不能直接调用自身。如果内联函数的函数体过大,编译器会自动的把这个内联函数变成普通函数。 - 宏定义是在预编译的时候把所有的宏名用宏体来替换,简单的说就是字符串替换;
内联函数则是在编译的时候进行代码插入,编译器会在每处调用内联函数的地方直接把内联函数的内容展开,这样可以省去函数的调用的开销,提高效率。 - 宏定义是没有类型检查的,无论对还是错都是直接替换,而内联函数在编译的时候会进行类型的安全检查,内联函数满足函数的性质,比如有返回值、参数列表等。
- 宏定义和内联函数使用的时候都是进行代码展开。不同的是宏定义是在预编译的时候把所有的宏名替换,内联函数则是在编译阶段把所有调用内联函数的地方把内联函数插入。这样可以省去函数压栈清栈,提高了效率。