实现机制
- 内联函数:由编译器在调用处将函数代码展开,像普通函数一样进行编译,遵循函数调用的规则,只是避免了函数调用的开销。例如:
inline int add(int a, int b) {
return a + b;
}
- 宏定义:由预处理器在预处理阶段进行文本替换,不进行语法检查。例如:
#define ADD(a, b) ((a) + (b))
作用范围
- 内联函数:和普通函数一样,遵循作用域规则。例如在某个函数内部定义的内联函数,其作用域仅限于该函数内部。
- 宏定义:从定义处到文件结束或被
#undef
取消定义。例如:
#define PI 3.14159
// 在文件此位置之后直到文件结束都可以使用PI宏
#undef PI
// 此处PI不再可用
类型检查
- 内联函数:进行严格的类型检查,因为它是函数,编译器会根据函数参数类型进行匹配和检查。例如:
inline double divide(double a, double b) {
return a / b;
}
// 如果传入非double类型参数,编译器会报错
- 宏定义:不进行类型检查,只是简单的文本替换。例如:
#define DIVIDE(a, b) ((a) / (b))
// 传入不同类型参数都不会报错,可能导致逻辑错误
内联函数优势场景
- 复杂逻辑:当函数体有较为复杂的逻辑,如循环、条件判断等,内联函数可以保持代码的逻辑性和可读性,同时获得类似宏的性能提升。例如:
inline int factorial(int n) {
int result = 1;
for (int i = 1; i <= n; i++) {
result *= i;
}
return result;
}
- 类型安全:对于需要严格类型检查的场景,内联函数可以避免宏定义因类型不匹配导致的错误。
宏定义适用场景
- 简单替换:对于非常简单的常量替换,如
#define MAX(a, b) ((a) > (b)? (a) : (b))
,宏定义简单直接,不需要像函数那样定义参数和返回类型。
- 与平台相关代码:在处理与平台相关的代码时,宏定义可以方便地通过
#ifdef
等预处理指令进行条件编译。例如:
#ifdef _WIN32
#define OS_NAME "Windows"
#elif defined(__linux__)
#define OS_NAME "Linux"
#endif