constexpr 仅在需编译期求值、类型推导或模板元编程时才有价值;必须用于数组长度、模板非类型参数、case标签、static_assert等常量表达式场景;C++14后函数限制放宽但仍有硬约束,推荐用if constexpr做编译期分支。

绝大多数情况下,constexpr 不会“自动加速”你的程序——它只在你明确需要编译期求值、类型推导或模板元编程时才产生实际价值;滥用反而可能拖慢编译速度、增加二进制体积。
什么时候必须用 constexpr 而不是 const
const 只保证运行时不可修改,constexpr 才真正承诺“这个值在编译期就能算出来”。只有后者能用在需要常量表达式的上下文中:
- 数组长度:
int arr[constexpr_func(5)];——const int n = 5;不行,constexpr int n = 5;可以 - 模板非类型参数:
std::array<int n></int>中的N必须是constexpr -
case标签:case constexpr_value:——const变量不被接受 - 静态断言:
static_assert(x > 0, "...");要求x是constexpr
constexpr 函数的限制和解法
C++14 起放宽了限制,但仍有硬约束:函数体不能含非 constexpr 操作(如 new、dynamic_cast、I/O),且所有分支都得能走通编译期路径。常见踩坑点:
- 局部变量默认不是
constexpr,要显式声明:constexpr int x = 10;,否则即使赋值为字面量也不参与编译期计算 - 循环可用,但必须能被编译器判定为有限次(C++20 支持
constexpr循环展开,但复杂逻辑仍可能失败) - 调用非
constexpr函数(哪怕只是std::sqrt的普通重载)直接导致整个表达式降级为运行时求值 - 推荐写法:用
if constexpr(C++17)做编译期分支,避免混入运行时逻辑
示例:
立即学习“C++免费学习笔记(深入)”;
constexpr int factorial(int n) {
if (n <= 1) return 1;
return n * factorial(n - 1); // C++14+ 允许递归,但深度受编译器限制
}
constexpr 对性能的真实影响
它不改变运行时指令,只把计算从运行时挪到编译时。收益仅出现在两类场景:
- 消除重复计算:比如多个地方用到
constexpr auto table = build_lookup_table();,编译器只算一次,生成只读数据段 - 启用优化:当编译器知道某值恒为
3,可直接内联、折叠条件、甚至删除死代码(if (len == 0)→ 消除整个分支)
但注意:若 constexpr 函数逻辑复杂(如解析字符串、递归深度大),会显著延长编译时间,且生成的 const 数据可能增大 .rodata 段——对嵌入式或热重载场景反而是负担。
容易被忽略的兼容性细节
C++11/14/17/20 对 constexpr 的支持差异很大,跨标准写法极易出错:
- C++11:函数体只能是单个
return表达式,不能有变量、循环、分支 - C++14:允许局部变量、
if、循环,但不能有try/catch或虚函数调用 - C++17:引入
if constexpr,支持编译期条件剔除代码;constexpr成员函数隐式为const - C++20:支持
constexprnew/delete、容器(std::vector还不行,但std::string_view和std::array可)、lambda 捕获
如果你的项目需兼容 GCC 7 或 Clang 6 以下版本,别用 C++17 的 if constexpr;想用 constexpr std::string,至少要 C++20 + GCC 13 / Clang 16。


















