一、定义ADD宏函数的常⻅问题
在学习inline之前,我们先来看宏定义函数,思考一下下面这几种宏实现ADD函数的方法正确吗?
// 实现⼀个ADD宏函数的常⻅问题
#define ADD(int a, int b) return a + b;
#define ADD(a, b) a + b;
#define ADD(a, b) (a + b)
正确的宏实现:
#define ADD(a, b) ((a) + (b))
下面思考几个问题:
3.1为什么不能加分号?
看一下下面这个场景:
//如果加了分号
#define ADD(a, b) ((a) + (b));
int main()
{
cout << ADD(1, 2) << endl;
//如果有分号,上边代码会变成这样:
cout << ((1) + (2)); << endl;//代码会发生错误
//或者做if语句的判断条件,也是不行的
if(ADD(1, 2))
{
}
return 0;
}
3.2为什么要加外⾯的括号?
看一下下面这个场景:
//如果不加外面的括号
#define ADD(a, b) (a) + (b)
int main()
{
cout << ADD(1, 2) * 3 << endl;
//如果不加外面的括号,上边代码会变成这样:
cout << (1) + (2) * 3 << endl;
//计算结果会变成1+2*3=7,而我们真正要的到的结果是9
return 0;
}
3.3为什么要加里⾯的括号?
看一下下面这个场景:
//如果不加里面面的括号
#define ADD(a, b) (a + b)
int main()
{
int x = 1;
int y = 2;
ADD(x & y, x | y); // -> (x&y+x|y)
//我们本意是先做x & y,再做x | y,最后在相加。
//而此时会先做y+x
return 0;
}
3.4宏定义的特性
宏函数虽然有众多缺点,但还是有其特性,其替换机制,在调用时不用建立函数栈帧。
C语⾔实现宏函数也会在预处理时替换展开,但是宏函数实现很复杂很容易出错的,且不⽅便调试,C++设计了inline⽬的就是替代C的宏函数。
二、inline
下面的inline修饰的ADD函数,就避免了宏函数众多问题:
#include<iostream>
using namespace std;
inline int ADD(int x, int y)
{
return x + y;
}
int main()
{
int x = 1, y = 2;
cout << ADD(x & y, x | y) << endl;
return 0;
}
(1)⽤inline修饰的函数叫做内联函数,编译时C++编译器会在调⽤的地⽅展开内联函数,这样调⽤内联函数就需要建⽴栈帧了,就可以提⾼效率。
也就是说,inline避免了宏的坑,也不用建立函数栈帧,提高了效率
(2)inline对于编译器⽽⾔只是⼀个建议,也就是说,你加了inline编译器也可以选择在调⽤的地⽅不展开,不同编译器关于inline什么情况展开各不相同,因为C++标准没有规定这个。inline适⽤于频繁调⽤的短⼩函数,对于递归函数,代码相对多⼀些的函数,加上inline也会被编译器忽略。
(3)vs编译器 debug版本下⾯默认是不展开inline的,这样⽅便调试,debug版本想展开需要设置⼀下以下两个地⽅。
(4) inline不建议声明和定义分离到两个⽂件,分离会导致链接错误。因为inline被展开,就没有函数地址,链接时会出现报错。