constexpr 是 C++ 中要求在编译期求值的关键字,用于变量、函数或对象;它强制参与常量表达式计算,否则编译失败,而 const 仅保证运行时不可修改。
constexpr 是 C++ 中用于声明「在编译期就能求值」的变量、函数或对象的关键词。它不是简单的“只读标记”,而是向编译器发出明确指令:这个东西必须能参与常量表达式计算——否则就是编译错误。
什么时候必须用 constexpr 而不能用 const
const 只表示运行时不可修改,constexpr 则要求值在编译期确定。以下场景会直接报错(如 GCC/Clang 提示 error: constexpr variable 'x' must be initialized by a constant expression):
- 作为数组长度:
int arr[constexpr_size];—— 若constexpr_size只是const int但初始化依赖运行时值(如cin >> x; const int n = x;),就不合法 - 非类型模板参数:
std::array a;要求N是constexpr整型 -
case标签值:switch (v) { case kValue: ... }中kValue必须是constexpr - 静态断言:
static_assert(condition, "...");的condition必须是constexpr布尔表达式
constexpr 函数的限制与放宽(C++11 → C++20)
早期 C++11 对 constexpr 函数极其严格:只能包含一个 return 语句,不能有循环、局部变量、分支(if)、异常等。C++14 开始大幅放宽,C++20 允许更多运行时特征(但仍需满足“所有调用路径都能在编译期求值”):
- C++14 起支持多条语句、
if/switch、局部变量、for/while循环(只要循环次数可静态推导) - 函数体仍不能含
new/delete、try/catch、asm等无法在编译期执行的操作 - 若函数被用于需要常量表达式的上下文(如模板参数),则本次调用必须能被编译器静态求值;否则即使函数声明为
constexpr,也会退化为普通运行时函数 - 示例:
constexpr int square(int x) { return x * x; }在int a[square(5)];中有效,在int b[square(n)];(n是运行时变量)中无效,但不会导致编译失败(只是不参与常量表达式)
常见误用与陷阱
看似写了 constexpr,实际并未达成编译期求值,甚至引发未定义行为: