内联函数
C99也支持,但C89不支持。
函数调用
在调用函数时,系统会保存现场的信息,然后调用函数返回后,再恢复现场。
下面这段看不懂或者觉得晕可以不看:
- CPU有三个指针,eip记录下一条指令,ebp记录栈底位置,esp记录栈顶位置。
- 主函数运行会根据变量的定义在栈区或者堆区申请空间。
- 遇到函数调用的时候会开辟一个栈区记录此时的ebp地址。
- 然后为形参开辟地址,根据实参给这些地址赋值。
- 再开辟两个栈区记录被调函数的返回值,和被调函数返回的地址。
- 被调函数执行完后将返回值赋给谁,如果有的话。
- 再从ebp的地址开始运行。刚才给被调函数的开辟的空间会被清理。包括形参、返回值、被调函数的返回位置。
所以,可能函数调用的时间和空间开销比执行函数体中的语句更大。那么,如果不调用,直接写在里面也许会更划算。
下面来看看怎么用:
#include <iostream>
using namespace std;
inline int sum(int a, int b);
int main()
{
int s;
//编译器在遇到内联函数调用时,会将函数调用展开为内联函数体,避免函数调用的时空开销,提升程序运行效率。
//内联函数中的代码不要太多,太复杂。
s=sum(3,4); //编译器会把这行处理为:s=3+4;
cout<<s<<endl;
return 0;
}
//定义内联函数,使用inline关键字
inline int sum(int a, int b)
{
return a+b;
}
值得注意的是:
- 内联函数也是一种请求,编译器可能会拒绝。现代C++编译器能够进行编译优化,因此一些函数即使没有inline声明,也可能被编译器内联编译。
- 编译器对于内联函数的限制并不是绝对的,内联函数相对于普通函数的优势只是省去了函数调用时压栈,跳转和返回的开销。因此,当函数体的执行开销远大于压栈,跳转和返回所用的开销时,那么内联将无意义。
- 另外,一些现代C++编译器提供了扩展语法,能够对函数进行强制内联
如:g++中的attribute((always_inline))属性。(没用过。) - 内联函数和宏定义的区别:
- 内联函数由编译器处理,直接将编译后的函数体插入调用的地方。
- 宏代码片段由预处理器处理,进行简单的文本替换,没有任何编译过程。
C++中内联编译的限制:
- 不能存在任何形式的循环语句
- 不能存在过多的条件判断语句
- 函数体不能过于庞大
- 不能对函数进行取址操作
- 函数内联声明必须在调用语句之前