一、从 C++11 引入
1. 常量表达式和 constexpr 关键字的概念
现代 C++ 从 C++11 开始引入了常量表达式(constant expression)和 constexpr 关键字,并在后续标准中不断更新。
常量表达式是指值不会改变且在编译过程中就能得到计算结果的表达式。用字面量或常量表达式初始化的 const 对象属于常量表达式,但用变量初始化的 const 对象则不是。
#include <iostream>
using namespace std;
const int a = 1; // a 是常量表达式
const int b = a + 1; // b 是常量表达式
int c = 1; // c 不是常量表达式
const int d = c; // d 不是常量表达式,因为编译期无法确定 c 的值是否会被修改
由于常量表达式的值在编译期即可确定,编译器可以直接进行优化替换。通过汇编代码对比可以看出,使用常量表达式的地方直接替换了数值,从而提升了运行时的性能。

C++11 引入 constexpr 关键字用于指定常量表达式,允许在编译时计算表达式的值。constexpr 可以修饰变量,但被修饰的变量必须是常量表达式,且必须用常量或常量表达式初始化,否则会报错。
constexpr 也可以修饰指针,此时修饰的是指针本身(顶层 const)。
注意区分顶层 const 和底层 const:对象本身被 const 修饰为顶层 const,指向的对象被 const 修饰为底层 const。大多数普通对象被 const 修饰时是顶层 const;指针被 const 修饰时,
*左边的 const 是底层 const,*右边的 const 是顶层 const;const 修饰引用时则是底层 const。
2. constexpr 修饰函数
constexpr 可以修饰函数,默认都是 inline 的,编译器会在编译时期执行计算。但由于函数逻辑比表达式复杂,C++11 对 constexpr 函数的要求非常严格:
- 参数和返回值必须是字面类型(如整型、浮点型、指针、引用等)
- 函数体只能包含一条语句,且必须是 return 语句
- 不能定义局部变量,不能有循环或条件语句
- 必须有返回值,且返回值为常量表达式
关键点: constexpr 函数的结果必须用常量表达式接收,才能触发编译优化。否则它仍像普通函数一样在运行时调用。





