【C++】内联函数理解
内联函数
内联函数的使用是对于C语言中宏函数的一种改进,他继承了宏的优点并避免了宏的缺点。
宏的优点:a. 代码复用性高 b. 宏函数减少栈帧建立,提高效率
宏的缺点:a. 可读性差 b. 没有类型安全检查 c. 不方便调试
C++基本不再建议使用宏,而是建议尽量使用const
、enum
、Inline
去替代宏。
以inline
修饰的函数就叫做内联函数。inline
在符合条件的情况下,编译时C++编译器会在调用内联函数的地方进行展开,此时就没有建立栈帧的开销,提高了程序运行的效率。
内联函数展开的查看方式:
(VS2019-Debug为例)
在不使用inline
情况下查看汇编代码:
/*inline */int ADD(int x, int y)
{
return x + y;
}
int main()
{
/*int ret1 = */ADD(1, 2);
/*int ret2 = */3 * ADD(1, 2);
return 0;
}
使用inline
后查看汇编代码:
inline int ADD(int x, int y)
{
return x + y;
}
这里编译器优化太过了,汇编代码没有显示,可以尝试通过接收返回值来查看。
可以看到汇编代码中没有了call
指令,而是将函数在调用的地方直接展开来使用了。
内联函数特性:
inline
是一种以空间换时间的做法,如果编译器将函数当成内联函数处理,在编译阶段,会使用函数体替换函数调用。这样做可能会使目标文件变得很大(缺点),但少了函数调用开销,提高了程序运行效率(优点)。inline
对于编译器只是一个建议,编译器会自动优化。一般建议:将函数规模较小(即函数不是很长,具体没有准确地说法,取决于编译器的内部实现)、不是递归、频繁调用的函数采用inline
修饰,否则编译器会忽略掉inline
特性。
一般来说,内联机制用于优化规模较小、流程直接、频繁调用的函数。很多编译器都不支持内联递归函数,而且一个75行的函数也不大可能在调用点内联地展开。 —— 《C++ prime》
以下是inline函数内部不同指令长度情况下,编译器自动对内联函数展开与否所做出的判断结果。
3. inline
不建议声明和定义分离,这样会导致链接错误。因为inline被展开了,就没有函数地址了,链接时就会找不到。
//func.h
inline int func(int x, int y);
//func.cpp
#include "func.h"
int func(int x, int y)
{
int ret = 0;
ret = x + y;
ret = x - y;
ret = x * y;
ret = x / y;
return ret;
}
//test.cpp
#include "func.h"
int main()
{
int ret = func(1, 2);
return 0;
}
所以再使用内联函数时,可以将inline
函数的定义放在.h
文件中。
//func.h
inline int func(int x, int y)
{
int ret = 0;
ret = x + y;
ret = x - y;
ret = x * y;
ret = x / y;
return ret;
}