constexpr 与 consteval
本课属于 Coddy C++ 学习旅程的“面向对象编程”单元。第 87 课,共 104 课。
C++ 允许在编译时而不是运行时进行计算,这可以显著提升性能。constexpr 关键字(C++11)和 consteval 关键字(C++20)让你可以控制表达式的求值时间。
如果传入常量参数,constexpr 函数可以在编译时求值,但也可以在运行时处理非常量输入:
#include <iostream>
constexpr int square(int n) {
return n * n;
}
int main() {
constexpr int compileTime = square(5); // 在编译时求值
int x = 7;
int runtime = square(x); // 在运行时求值
std::cout << compileTime << "\n"; // 25
std::cout << runtime << "\n"; // 49
}需要确保在编译时求值时,请使用 consteval。consteval 函数必须生成常量,使用运行时值调用它会导致编译错误:
consteval int factorial(int n) {
return n <= 1 ? 1 : n * factorial(n - 1);
}
int main() {
constexpr int result = factorial(5); // OK:120 在编译时计算得出
// int x = 5;
// int bad = factorial(x); // ERROR:x 不是常量
}你还可以将 constexpr 用于变量,甚至用于类构造函数,从而在编译时创建整个对象。这对于查找表、配置值或程序运行期间不会变化的数据尤其有用。
挑战
简单你将把代码组织到 3 个文件中:
MathUtils.h:定义编译时数学函数。创建以下函数:
cube:一个constexpr函数,接收一个int,并返回它的立方(n * n * n)triangularNumber:一个constexpr函数,使用公式 n * (n + 1) / 2 计算第 n 个三角数。在此任务中,我们只会在编译时上下文中调用它,并将结果存储在constexpr变量中。sumOfSquares:一个constexpr函数,接收两个整数,并返回它们的平方和(a*a + b*b)
Config.h:使用编译时常量创建一个配置结构体。定义一个
Config结构体,并添加一个constexpr构造函数,接收 3 个整数:width、height和depth。将它们存储为公有成员。再添加一个名为volume()的constexpr方法,返回 width * height * depth。在结构体下方,创建一个名为
DEFAULT_CONFIG的constexpr全局常量,并将其初始化为 10、20 和 5。main.cpp:从输入中读取两个整数,表示运行时的值。首先,创建
constexpr变量,演示编译时求值:- 将
cube(4)存储在一个 constexpr 变量中,并打印:Cube of 4: [value] - 将
triangularNumber(10)存储在一个 constexpr 变量中,并打印:10th triangular number: [value] - 打印默认配置的体积:
Default volume: [value]
然后,使用两个输入值,演示
constexpr函数也可以在运行时使用:- 使用第一个输入调用
cube(),并打印:Cube of [input]: [result] - 使用两个输入调用
sumOfSquares(),并打印:Sum of squares: [result]
- 将
例如,输入 3 和 4 时:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25输入 5 和 12 时:
Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169亲手试试
#include <iostream>
#include "MathUtils.h"
#include "Config.h"
using namespace std;
int main() {
// 从输入中读取两个整数
int input1, input2;
cin >> input1;
cin >> input2;
// TODO:演示编译时求值
// 创建一个 constexpr 变量来存储 cube(4) 的值,并输出:"Cube of 4: [value]"
// TODO:创建一个 constexpr 变量来存储 triangularNumber(10) 的值
// 并输出:"10th triangular number: [value]"
// TODO:输出默认配置的音量:"Default volume: [value]"
// TODO:演示如何在运行时使用 constexpr 函数
// 用 input1 调用 cube(),并输出:"Cube of [input1]: [result]"
// TODO:用两个输入值调用 sumOfSquares()
// 并输出:"Sum of squares: [result]"
return 0;
}
这节课包含一个小测验。开始学习即可作答,并记录你的进度。
面向对象编程中的所有课
12现代 C++ 特性
移动语义与右值完美转发深入了解 Lambda 表达式std::function 与 std::bindconstexpr 与 consteval结构化绑定optional、variant 和 any自己练习: C++ 在线编译器