文章目录
C++20 引入了
consteval
和
constinit
两个新关键字,它们与
constexpr
一起,为编译时计算和变量初始化提供了更强大的支持。以下是对这两个特性的详细介绍和用法。
1. consteval
:强制编译时计算
consteval
是 C++20 中引入的一个关键字,用于定义只能在编译时计算的函数。与 constexpr
函数不同,consteval
函数必须在编译时计算,而不能在运行时调用。
语法
consteval int add(int a, int b) {
return a + b;
}
特点
- 强制编译时计算:
consteval
函数的所有调用都必须在编译时完成,不能在运行时调用。 - 参数限制:函数参数必须是编译时已知的常量表达式。
- 适用场景:用于需要在编译时完成的复杂计算,例如生成常量数组或类型特征。
示例
consteval int fib(int n) {
int a = 0, b = 1;
for (int i = 0; i < n; i++) {
a = b;
b = a + b;
}
return a;
}
int main() {
constexpr int result = fib(10); // OK,fib(10) 是编译时计算的
// int runtime_result = fib(a); // 错误,变量 a 不是编译时常量
return 0;
}
2. constinit
:确保编译时初始化
constinit
是 C++20 引入的另一个关键字,用于确保具有静态或线程存储期限的变量在编译时完成初始化。
语法
constinit int global_var = 42;
特点
- 编译时初始化:
constinit
确保变量在编译时初始化,避免运行时动态初始化。 - 非常量变量:与
constexpr
不同,constinit
不要求变量是常量,变量可以在运行时修改。 - 适用范围:只能用于具有静态或线程存储期限的变量,不能用于局部变量。
示例
constinit int global_var = 42; // 编译时初始化
int main() {
global_var = 100; // 允许修改
return 0;
}
3. consteval
和 constinit
的区别
特性 | consteval | constinit |
---|---|---|
作用 | 强制函数在编译时计算 | 确保变量在编译时初始化 |
适用对象 | 函数 | 具有静态或线程存储期限的变量 |
运行时调用 | 不允许 | 允许(变量可修改) |
编译时要求 | 参数必须是常量表达式 | 初始化表达式必须是编译时可计算的 |
4. 使用场景
-
consteval
:- 用于生成编译时常量,例如数组大小或类型特征。
- 避免运行时计算,提升性能。
-
constinit
:- 避免静态初始化顺序问题(SIOF)。
- 确保全局变量或静态变量在编译时初始化,减少运行时开销。
5. 注意事项
-
consteval
:- 不能与运行时变量一起使用,否则会导致编译错误。
- 适用于需要在编译时完成的复杂计算。
-
constinit
:- 只能用于静态或线程存储期限的变量。
- 初始化表达式必须是编译时可计算的。
总结
consteval
和 constinit
是 C++20 引入的两个强大工具,分别用于强制编译时计算和确保编译时初始化。它们与 constexpr
一起,为现代 C++ 的编译时优化提供了更丰富的支持。