Menu
CoddyTech

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 用于变量,甚至用于类构造函数,从而在编译时创建整个对象。这对于查找表、配置值或程序运行期间不会变化的数据尤其有用。

challenge icon

挑战

简单

你将把代码组织到 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;
}
quiz icon自我测试

这节课包含一个小测验。开始学习即可作答,并记录你的进度。

面向对象编程中的所有课

自己练习: C++ 在线编译器