[Effective C++]条款02:尽量以const, enum, inline替换#define

1、C++预处理器

1.1)、预处理器是编译器的一部分,它在实际编译之前对源代码进行处理。预处理器指令以 # 开头,常见的预处理器指令包括:

  • #include:用于包含头文件。
  • #define:用于定义宏。
  • #ifdef、#ifndef、#endif:用于条件编译。
  • #pragma:用于提供编译器特定的指令。

1.2)、预处理器的功能:

  • 文本替换:例如,宏定义会将标识符替换为指定的文本。(#define)
  • 条件编译:根据条件决定是否编译某段代码。(#ifdef等)
  • 文件包含:将其他文件的内容插入到当前文件中。(#include)

2、宏定义
宏定义是预处理器的一部分,通过 #define 指令实现。宏的本质是文本替换,它在预处理阶段将宏名替换为指定的文本。
2.1)、宏定义的用法

  • 简单宏
#define PI 3.14159

在代码中使用 PI 时,预处理器会将其替换为 3.14159。

  • 带参数的宏
#define MAX(a, b) ((a) > (b) ? (a) : (b))

在代码中使用 MAX(x, y) 时,预处理器会将其替换为 ((x) > (y) ? (x) : (y))。

  • 多行宏
    使用 \ 将宏定义扩展到多行:
#define PRINT_SUM(a, b) \
    std::cout << "Sum: " << (a) + (b) << std::endl;

2.2)、宏的注意事项

  • 副作用:由于宏是简单的文本替换,可能会导致意外的副作用。例如:
#define SQUARE(x) (x * x)
int result = SQUARE(2 + 3); // 替换为 (2 + 3 * 2 + 3),结果是 11 而不是 25

正确的写法应该是:

#define SQUARE(x) ((x) * (x))
  • 调试困难:宏在预处理阶段被替换,编译器看不到宏的原始定义,因此调试时可能会遇到困难。
  • 类型不安全:宏不进行类型检查,可能导致类型错误。

3、预处理器与宏定义的区别
在这里插入图片描述

4、替代宏的方案
4.1)、常量定义
使用 const 或 constexpr 替代简单的宏:

constexpr double PI = 3.14159;

4.2)、内联函数
使用 inline 函数替代带参数的宏:

inline int max(int a, int b) {
    return a > b ? a : b;
}

4.3)、枚举
使用 enum 替代常量宏:

enum { MAX_SIZE = 100 };

5、总结:

  • 预处理器是 C++ 编译前的处理工具,宏定义是预处理器的一部分。
  • 宏定义主要用于文本替换,但容易引发副作用和调试困难。因为宏定义不会进入记号表
  • 现代 C++ 推荐使用 const、constexpr、inline 函数等替代宏,以提高代码的安全性和可读性。

| 思维导图笔记:
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值