C++中constexpr与consteval的本质区别
C++中constexpr(C++11)和consteval(C++20)都用于编译期求值,它们的本质区别是什么?constexpr函数是否一定在编译期执行?为什么需要consteval(立即函数)来强制编译期求值?
回答
小字辈
constexpr(C++11起):修饰函数/变量,指示可以在编译期求值。
- 非强制:如果调用时参数不是编译期常量,可以降级为运行时执行
- constexpr函数内部可以有
if constexpr、循环等(C++14放宽) - C++17起constexpr lambda
- C++20起: 虚函数constexpr、try-catch constexpr、dyn alloc constexpr
consteval(C++20):修饰函数,必须只在编译期求值。
- 强制:所有调用必须是编译期常量表达式
- 不能在运行时调用
- 典型用途:编译期字符串处理(哈希计算)、类型转换、元编程辅助
核心区别:
constexpr int f(int x) { return x * 2; }
consteval int g(int x) { return x * 2; }
int a = f(5); // 编译期求值
int b = f(rand());// 运行时求值(OK)
int c = g(5); // 编译期求值
int d = g(rand());// 错误!rand()不是编译期常量
constinit(C++20):保证变量在静态初始化阶段完成初始化。
选择建议:
- 可用于编译期也可用于运行时的函数→constexpr
- 必须编译期执行的函数(如模板参数计算)→consteval
- 需要静态初始化保证的全局变量→constinit