[c++]宏函数与内联函数
目录
一、宏函数
1、宏函数是什么?
2、错误代码示范
2.1、错误示例1
2.2、错误示例2
2.3、错误示例3
2.4、正确示例
3、宏的优点和缺点
二、内联函数
1、内联函数是什么
2、为什么要有内联函数
3、查看release模式下inline函数
4、内联函数注意事项
5、内联函数的优点和缺点
一、宏函数
1、宏函数是什么?
宏函数(Macro Function)是一种在编译预处理阶段展开的代码替换机制,通常由预处理器(如C/C++中的#define)实现。它通过定义一段代码模板,在调用时直接替换到源代码中,而非像普通函数那样通过调用栈执行。
2、错误代码示范
2.1、错误示例1
#define int Add(int x,int y) return x+y;//错误示例1
// 加了 返回值 形参 和 分号
2.2、错误示例2
#define Add(x,y) x+y //错误示例2
int main()
{cout << Add(10,20)*20 << endl;//-> 10+20*20=410 error return 0;
}
2.3、错误示例3
#define Add(x,y) (x+y) //错误示例3
int main()
{int a = 1, b = 2;Add(a | b, a & b);//->(a|b+a&b) 优先级 + 大于 | 大于 & ,会先执行b+areturn 0;
}
2.4、正确示例
#define Add(x,y) ((x)+(y))
int main()
{for (int i = 0; i < 1000; i++){cout << Add(i, i + 1) << endl;;}return 0;
}
3、宏的优点和缺点
宏函数的优点是在预处理阶段直接展开,替换代码,不需要建立栈帧,可以提高调用效率。
缺点是复杂,容易出错,并且可读性较差,不利于调试,无类型安全检查,在预处理阶段替换了。
二、内联函数
1、内联函数是什么
C++提出inline函数来解决宏函数的缺点,在调用阶段展开,以inline修饰的函数叫做内联函数,编译时C++编译器会在调用内联函数的地方展开,没有函数调用建立栈帧的开销,可以提升程序运行的效率。
2、为什么要有内联函数
函数在调用时有建立栈帧(栈上开空间)的开销,如果函数频繁调用,要建立非常多的栈帧,因此可以通过内联函数进行优化。
3、查看release模式下inline函数
默认debug模式下,inline不会起作用,会call Add函数地址。可以在release模式下,查看编译器生成的汇编代码是否存在call Add函数地址。

示例

内联函数展开后汇编代码解释
mov eax, dword ptr [rsp+20h]
[rsp+20h] 是循环变量 i 在栈上的位置
将 i 读入 eax。mov ecx, dword ptr [rsp+20h]
再次将 i 读入 ecx。lea eax, [rax+rcx+1]
计算 rax + rcx + 1,即 i + i + 1 = 2*i + 1。
这里就是内联后的加法运算,没有 call Add 指令。mov edx, eax
将结果 2*i+1 存入 edx,作为 operator<< 的参数。后续是调用 std::cout 输出 edx 的值,再输出 std::endl。
4、内联函数注意事项
4.1、宏函数、内联函数都适用于短小的频繁调用的代码(使用场景),但是inline对编译器只是建议,至于最终成为inline取决于编译器。例如函数较长,递归函数,这些函数即使加了inline编译器也不会让其成为内联函数。
4.2、内联函数声明与定义不分离,因为预处理Test_Inline.cpp头文件展开,得到内联函数inline void Func(int i) 的声明,编译阶段可以通过,但是在链接阶段,由于inline函数已经展开没有地址,不会进符号表,链接不上地址,在链接阶段会报错。

5、内联函数的优点和缺点
内联函数的优点是在调用时直接展开,不需要建立栈帧,可以提高调用效率。
缺点是代码不复杂,不容易出错,有较好的可读性,便于调试
