将C++宏常量替换为constexpr的优势有哪些?
原本的宏定义代码:
#define kMaxLength 50 #define kSlipsModeSelect 0 #define kSlipsModeAll 1 #define kStatusBarIconWidth 20
上述宏定义触发的代码分析提示:
Macro can be converted to
constexpr
工具推荐的修改方案:
constexpr auto kMaxLength = 50; constexpr auto kSlipsModeSelect = 0; constexpr auto kSlipsModeAll = 1; constexpr auto kStatusBarIconWidth = 20;
将这类数值类宏替换为constexpr常量的收益主要有以下几点:
- 类型安全:宏是预处理器纯文本替换逻辑,没有任何类型校验,很容易因为隐式类型转换引入难以排查的bug。
constexpr是符合C++类型系统的常量,编译器会自动做类型检查,传参、赋值时类型不匹配会直接给出编译提示,从源头避免这类问题。 - 作用域可控:宏没有作用域限制,只要完成定义之后所有代码都会被替换,非常容易出现命名冲突,比如不同依赖库定义了同名宏就会导致代码出现莫名其妙的编译错误。
constexpr遵守C++的作用域规则,可以放在命名空间、类、函数内部,不会随意污染全局命名空间,同名常量在不同作用域下互不干扰。 - 调试更方便:宏在预编译阶段就已经被替换为字面量,调试时无法看到宏的符号名,只能看到最终的数值,排查问题时很难对应到具体的常量定义。
constexpr是正规的C++符号,调试过程中可以正常看到常量名称,定位问题效率高很多。 - 没有预处理器的语法坑:宏做运算时很容易因为运算符优先级出问题,比如
#define DOUBLE(x) x*2,传入1+1时会被展开为1+1*2,结果和预期不符。constexpr的语法和普通C++代码完全一致,不会出现这类预处理器带来的异常逻辑。 - 支持更复杂的编译期计算:如果后续需要基于现有常量做更复杂的编译期运算,
constexpr可以直接参与表达式计算,编译期就能得到结果,运行效率和宏完全一致,还能保证逻辑的可读性和正确性。 - 不会出现意外替换:如果代码中存在和宏同名的变量、函数、类成员,预处理器会不加区分全部替换,往往会导致非常诡异的编译错误,排查成本极高。
constexpr受作用域规则约束,不会出现这类无差别替换的问题。
内容的提问来源于stack exchange,提问作者Andrew Truckle
相关产品推荐
相关产品推荐

