应尽量避免宏,优先使用const、constexpr、enum class和inline变量:宏无类型、不参与检查;constexpr提供编译期求值与类型安全;enum class避免命名冲突;inline函数替代宏函数防展开错误;inline变量解决跨文件常量定义问题。

宏(#define)在现代 C++ 中应尽量避免,优先使用 const、constexpr、enum class 和 inline 变量——这不是教条,而是为了类型安全、调试友好、作用域可控和编译器优化更充分。
宏没有类型,而 const/constexpr 有完整类型信息
宏只是文本替换,不参与类型检查。比如:
#define MAX_SIZE 100 int arr[MAX_SIZE]; // OK auto x = MAX_SIZE + 1.5; // 隐式转成 int,可能丢失精度,且编译器不警告
换成 constexpr 后,类型明确,还能参与模板推导:
constexpr int MAX_SIZE = 100; auto x = MAX_SIZE + 1.5; // x 是 double,语义清晰,无隐式截断
-
const适合运行期常量(如读配置后赋值) -
constexpr更推荐:编译期可求值,支持用在需要常量表达式的地方(数组大小、模板参数、switch分支等) - 基本类型优先用
constexpr,避免裸#define
枚举值用 enum class 替代宏定义的状态码
传统宏定义状态值易冲突、无命名空间、不可调试:
立即学习“C++免费学习笔记(深入)”;
#define SUCCESS 0 #define ERROR_FILE 1 #define ERROR_NET 2 // 一不小心重定义或与其他头文件冲突
enum class 天然隔离作用域、有底层类型、支持强类型比较:
enum class ResultCode : int {
Success = 0,
ErrorFile = 1,
ErrorNet = 2
};
ResultCode r = ResultCode::Success; // 类型安全,IDE 可跳转、补全- 避免裸
enum(会隐式转为 int,失去类型保护) - 显式指定底层类型(如
: int)确保跨平台一致 - 需要遍历或反射时,可用
magic_enum等现代库辅助
内联函数比函数式宏更安全、更可调试
宏函数不求值参数、无作用域、容易因括号缺失出错:
#define SQUARE(x) x * x int a = SQUARE(2 + 3); // 展开为 2 + 3 * 2 + 3 → 11,不是 25!
用 inline constexpr 函数替代,语义清晰、支持重载、能被调试器单步:
inline constexpr int square(int x) { return x * x; }
int a = square(2 + 3); // 正确计算为 25,且编译器大概率内联- 简单逻辑优先写
inline constexpr函数(C++17 起无需手动加inline,但显式写更清晰) - 模板函数天然内联,也适合泛型场景(如
square)(x) - 宏函数仅在极少数需操作预处理器符号(如
__FILE__)时保留
全局常量用 inline 变量替代宏或 extern 声明
C++17 之前,跨文件共享常量常靠 extern const 声明 + 单独定义,繁琐易错;宏又没类型。现在直接用 inline constexpr 变量:
// config.h inline constexpr double PI = 3.1415926535897932385; inline constexpr std::string_view APP_NAME = "MyApp";
头文件中定义,多处包含不报 ODR 错误,类型安全,且所有编译单元看到同一地址(inline 保证)。
- 适用于字面量、字符串视图、自定义字面量类型(需满足 literal type)
- 比
static const更优:后者每个 TU 一份副本,inline是真正“一个定义” - 类内静态常量也可用
inline static constexpr直接定义











