“#define”和inline有相同的行为吗?
不,它们并不相同!
宏和内联函数之间存在许多差异。
- 评估次数不同
作为内联函数参数传递的表达式只会被评估一次。
在某些情况下,作为宏参数传递的表达式可能会被评估多次。
每次在宏中使用一个参数时,该参数都会被评估。
代码示例:
#define max(a,b) (a>b?a:b)
int main()
{
int a = 0;
int b = 1;
int c = max(a++, b++);
cout << a << endl << b << endl;
return 0;
}
意图可能是打印1和2,但宏会扩展为:
int c = a++ > b++ ? a++ : b++
b被增加了两次,程序打印出1和3。
- 谁评估它们
内联函数由编译器评估,而宏在预编译时由预编译器评估。
- 类型检查
内联函数遵循正常函数强制执行的所有类型安全协议。检查参数类型,并正确执行必要的转换。编译器在将内联函数放入符号表之前执行返回类型检查、函数签名。
它们可以被重载以针对不同类型的数据执行适当的操作。
与内联函数相比,宏更容易出错。它们的参数没有类型(该宏适用于任何算术类型的对象)。在编译过程中不进行错误检查。
代码示例:
#define MAX(a, b) ((a < b) ? b : a)
int main( void)
{
cout << "Maximum of 10 and 20 is " << MAX("20", "10") << endl;
return 0;
}
可以将字符串传递给执行一些整数运算的宏,而宏不会抱怨!
- 是建议还是命令?
内联函数只是向编译器提出的建议。是否展开函数是编译器的决定。
宏始终会被展开。
- 调试方面呢?
内联函数可以轻松调试,因为可以在内联函数定义处设置断点,逐步调试方法。
宏不能用于调试,因为它们在预编译时展开。
2 * ROUND_DOWN(178, 32)
将会导致程序出现问题。请改用#define ROUND_DOWN(a,b) ((a)-(a)%(b))
(注意额外的括号)。总之,两种方法的行为不会完全相同。 - user142019ROUND_DOWN(x++, y)
,看看会发生什么。 - Fred Larson