constexpr:编译期求值的秘密
constexpr 是 C++11 引入的关键字,表示一个表达式或函数可以在 编译期求值。
constexpr 修饰变量
编译期计算值。constexpr 本身不是类型限定符,但它对变量 隐含顶层 const。
举例说明:
1 | constexpr int* ptr = &val; |
ptr本身不可变(不能指向别的地址)。- 但可以通过
ptr修改val的值(*ptr = 10;是合法的)。
constexpr 修饰函数
告诉编译器:
“如果参数都是编译期常量,编译的时候就把结果算出来;如果不是,就把它当作普通函数在运行期执行。”
为什么要使用 constexpr?
把运行时的计算提前到了编译期,减少了运行时开销。
如何实现编译时计算?
这是 constexpr 的核心,也是一直困扰我的问题。
我困扰的点是:AST 解释执行 这个东西除了教学以外还有什么应用场景?
之前在写 Pinky 编译器 的时候,第一个实现的执行方式就是遍历 AST 执行,但我一直很难想到这种执行方式的其他实际应用场景。今天突然想到 constexpr,来看了一下它的实现,终于明白了它的使用场景。
constexpr 的实现原理
正如上面所说,constexpr 实现编译时计算的方式就是 遍历 AST 解释执行。
- 遍历顺序:求值顺序驱动的遍历。
- 大部分是 后序遍历。
- 也有特殊情况:如赋值语句(先右后左)、逻辑与/或(短路求值)等。
- 执行宿主:具体执行计算的宿主语言当然就是 C++。
- 结果处理:执行结果直接填入目标位置。
实例:GCC 中的 AST 表示
以 4 + 5 为例,这个 PLUS_EXPR 在 GCC 的 AST 树中的表示如下:

这个属于 binop 中的 plus,遍历规则是 后序遍历:
- 先分别拿到
PLUS_EXPR的左右子树的值(4 和 5)。 - 然后用宿主语言 C++ 计算结果(9)。
- 结果直接替换到 AST 中或填入目标位置。
后续计划
后续会写一些编译器 / GC 相关的博客,例如:
- 不同编译器生成 AST 的方式(递归下降、优先级爬升)
- 不同类型语言(编译型、纯解释型、解释 + JIT 型)的 GC 实现差异
All articles on this blog are licensed under CC BY-NC-SA 4.0 unless otherwise stated.






