优先用 const 或 constexpr 而非 #define 定义常量,因前者具类型安全、作用域控制、可调试和可取地址等优势;仅当需条件编译、标识符拼接、可变参数宏等预处理能力时才用 #define。

直接说结论:优先用 const(或 constexpr),不用 #define 定义常量,除非你明确需要宏的文本替换能力。
为什么 const 比 #define 更安全
根本区别在于: #define 是预处理器指令,在编译前做纯文本替换,不经过类型检查;const 是 C++ 语言级的常量,有类型、作用域和内存地址(除非被优化掉)。
-
#define PI 3.14159→ 替换后可能变成double x = 3.14159f;(拼写错误导致精度丢失),编译器完全不会报错 -
const double PI = 3.14159;→ 类型固定为double,赋值给float会触发隐式转换警告(取决于编译器设置) -
const变量可取地址:&PI合法;#define宏不能取地址 - 调试时,
const变量名通常保留在符号表中,GDB 能看到;#define宏在调试信息里已消失
const 和 constexpr 怎么选
两者都用于定义常量,但语义和使用场景不同:
-
const表示“运行期不可修改”,但初始化可以是非编译期常量:const int x = rand();合法(C++11 起) -
constexpr要求“必须在编译期求值”,可用于模板参数、数组长度、case标签等:constexpr int N = 10; int arr[N];合法;而const int N = 10;在 C++11 中不足以支持变长数组(实际依赖编译器扩展) - 对于字面量常量,优先写
constexpr:constexpr double PI = 3.1415926;,它隐含const,且更明确表达“编译期可用”
#define 还有什么不能被替代的场景
不是所有宏都能被 const 或 constexpr 替代。真需要 #define 的典型情况:
立即学习“C++免费学习笔记(深入)”;
- 条件编译:
#ifdef DEBUG、#if __cplusplus >= 201703L - 生成标识符(token pasting):
#define DECLARE_TYPE(name) struct name##_t { ... }; - 可变参数宏(C++11 起可用可变模板替代,但宏仍更轻量):
#define LOG(fmt, ...) printf(fmt, ##__VA_ARGS__) - 跨翻译单元的简单配置开关(如
#define MAX_CONN 1024),虽可用inline constexpr替代,但某些嵌入式或遗留构建系统仍依赖宏
constexpr int MAX_CONN = 1024; const double EPSILON = 1e-9; // ❌ 不推荐 #define MAX_CONN 1024 #define EPSILON 1e-9 // ✅ 更好:类型安全 + 调试友好 + 可取地址
最易被忽略的一点:宏没有作用域,哪怕写在函数内部,也是全局生效;而 const 和 constexpr 遵守正常的块作用域规则——这点在大型项目中直接影响命名冲突和维护成本。











