C++中的constexpr有什么用?(编译期常量)

constexpr 使计算在编译期完成,生成真正常量;要求变量或函数入参均为编译期常量,支持数组大小、模板参数等场景,并区别于 const(运行时只读)和 consteval(强制仅编译期调用)。

constexpr 让你把计算搬到编译期完成,生成真正的常量,不是运行时才确定的“只读变量”。

让变量成为编译期常量

加了 constexpr 的变量,必须在编译期就能算出值,否则报错。它比 const 更严格——const 只保证不修改,值可以来自运行时(比如函数返回);而 constexpr 强制要求值已知、不可变、可参与编译期逻辑。

  • int x = 5; constexpr int y = x * 2; → 错误:x 不是编译期常量
  • constexpr int a = 10; constexpr int b = a + 3; → 正确:所有值都确定,b 就是 13,存进符号表,不占运行时内存

让函数支持编译期求值

标记为 constexpr 的函数,不等于“只能在编译期调用”,而是“如果入参都是编译期常量,就尝试在编译期算出结果”。它写法受限(C++14 后宽松很多),但好处明显:

  • 能用在需要常量表达式的地方:数组大小、模板非类型参数、case 标签等
  • 避免重复运行时计算:同一个 constexpr 函数被多处以常量调用,编译器只算一次
  • 例如:constexpr int square(int n) { return n * n; } int arr[square(5)]; → 合法,arr 是长度为 25 的数组

让类和构造函数参与编译期构建

C++11 起支持 constexpr 构造函数,只要所有成员都能用常量初始化,整个对象就能是编译期常量。C++20 还允许 constexpr 成员函数中使用循环、局部变量甚至 try-catch(有限制)。

立即学习“C++免费学习笔记(深入)”;

  • 常见用途:定义编译期字符串、固定大小容器、数学常量类型(如 constexpr Vec3{1,0,0}
  • 关键点:所有数据成员必须是字面类型(literal type),且构造过程不能有副作用

和 const、consteval 的区别

const 是运行时只读语义;constexpr 是编译期可求值能力;consteval(C++20)更进一步——强制只能在编译期调用,哪怕传入运行时值也会编译失败。

  • 想写一个“保证不产生运行时开销”的工具函数?用 constexpr
  • 想确保某个值绝对进符号表、零成本?优先声明为 constexpr 变量
  • 想彻底禁止运行时调用(比如加密密钥生成逻辑)?选 consteval

基本上就这些。它不是语法糖,是让编译器“看懂你的意图”,从而优化、验证、甚至提前报错的关键机制。