C++中优先使用const或constexpr,仅在条件编译、头文件卫士、字符串化或token拼接等预处理不可替代场景才用#define。
直接说结论:C++ 中优先用 const(或 constexpr),#define 仅在宏替换不可替代的场景下使用,比如条件编译、头文件卫士、或字符串化/拼接。
#define
预处理器不关心类型、作用域和语法,只做文本替换。所以以下情况绕不开 #define:
#ifdef / #ifndef 条件编译——const 变量无法参与预处理判断#ifndef MY_HEADER_H … #define MY_HEADER_H
#define STR(x) #x → STR(42) 展开为 "42"
#define CONCAT(a, b) a##b → CONCAT(foo, _bar) 得 foo_bar
const 比 #define 安全得多#define PI 3.14159 看似简单,但它是全局文本替换,没有类型、无作用域、不进调试符号表,且容易因括号缺失出错(如 #define SQUARE(x) x*x 遇到 SQUARE(a + b) 就崩成 a )。
const 则是真正的变量(或引用),受编译器类型检查和作用域控制:
const double PI = 3.14159; // 类型明确,作用域可控
const int MAX_SIZE = 1024; // 编译期常量(C++17 起可作数组维度)
constexpr int fib(int n) { ... } // C++11 起支持编译期计算const 变量有地址,能取地址、传引用、用于模板非类型参数(C++17+)constexpr 还能保证编译期求值,比 const 更强(如 constexpr int arr[N] 中 N 必须是 constexpr)PI 的值;#define 在调试器里根本搜不到定义字符串常量时,#define MSG "hello" 和 const char* MSG = "hello"; 行为不同:
#define 是纯文本替换,多次使用可能生成多份副本(虽然现代编译器常优化)const char* 是指针,指向同一字符串字面量;若要确保内容不可改且避免指针语义,该用 const char MSG[] = "hello"; —— 这会分配数组,且长度可推导:sizeof(MSG) 包含末尾 \0
const int N = 10; 在 C++11 前不能用于 int arr[N];(VLA 不合法),必须用 constexpr int N = 10; 或 #define N 10
真正复杂的地方不在语法,而在「是否需要预处理介入」——一旦涉及 #if、头文件包含控制、或 token 操作,就只能上 #define;其余所有数据常量,都该交给 const 或 constexpr 管理。