1.为什么要引入内联函数?
我们可能会用宏函数来完成两个数的相加
正确的书写方式是#define ADD(x,y) ((x)*(y))
但我们容易错误忘记最后还要再加一个大括号,不然容易出错
比如
#define ADD(x,y) x*y
#include<iostream>
using namespace std;
int main()
{
int a=ADD(5+1,8+1);
return 0;
}
a的值是5+1*8+1=14;而不是想象中的54
除此之外宏函数类型还有检查不严格,安全性低等缺点
不过宏函数的一个优势就是不需要建立栈帧,提高了调用效率。而对于C++而言,为了解决C语言的这种缺陷,C++提供的解决方案就是内联函数。
2.什么是c++内联函数?
我们引入inline这个关键字
以 inline 修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数压栈的开销,内联函数提升程序运行的效率。
下面举个例子
#include<iostream>
using namespace std;
inline void A(int a)//前面加了个inline
{
cout<<a<<endl;
}
int main()
{
int w=99;
A(w);//A(w)直接展开为{a=99;cout<<a<<endl;
}
函数A()就是一个内联函数
3.内联函数和普通函数的区别
你可能会好奇,这函数定义前不加inline和加了inline有什么区别,这体现在他们被调用的时候
常规函数调用:执行到函数调用指令时,程序将在函数调用后立即存储该指令的内存地址,并将函数参数复制到堆栈,跳到标记函数起点的内存单元,执行函数代码,然后跳回到地址被保存的指令处(这与阅读文章时停下来看脚注,并阅读完脚注后返回以前阅读的地方类似)
内联函数调用:程序无需跳到另一个位置处执行代码,再跳回来。
每调用一次内联函数,程序就会生成一次包含该函数代码的副本,并自动替换其调用语句,使函数调用过程速度变快一点点,代价是需要占用更多内存
上面两组代码的功能一样,但是执行的过程有所不同,内联函数会自动展开调用语句,省去了部分函数栈帧开销,但这是以牺牲内存为代价的(因为语句变多了)
4.内联函数的优点和注意事项
1.不需要建立函数栈帧。
2.可读性强,且不易出错。
3.可以调试
4.使用起来简单。
但我们并不是要把所有的函数都弄成为内联函数,内联函数使用于短小而频繁调用的函数。如果函数比较长、又或者是递归函数不要让其称为内联函数。此外注意内联函数应省略原型,将函数头和所有函数代码放在本应提供原型的地方
函数前面加上inline一定会有效果吗?
答:不会,使用内联inline关键字修饰函数只是一种提示,编译器不一定认。
如果不加inline就不是内联函数了吗?
答:存在隐式内联,不用inline关键字,C++中在类内定义的所有函数都自动称为内联函数。
内联函数一定就会展开吗?
答:其实和第一个问题类似,还是看编译器认不认。
在什么情况下内联函数会展开?
答:首先需要满足有inline修饰或者是类中的定义的函数,然后再由编译器决定。