Menu
Coddy logo textTech

constexpr und consteval

Teil des Abschnitts Objektorientierte Programmierung der C++-Journey von Coddy — Lektion 87 von 104.

C++ ermöglicht es, Berechnungen zur Kompilierzeit statt zur Laufzeit durchzuführen, was die Performance erheblich verbessern kann. Das Schlüsselwort constexpr (C++11) und das Schlüsselwort consteval (C++20) geben Ihnen die Kontrolle darüber, wann Ausdrücke ausgewertet werden.

Eine constexpr-Funktion kann zur Kompilierzeit ausgewertet werden, wenn sie konstante Argumente erhält, aber sie kann auch zur Laufzeit mit nicht-konstanten Eingaben ausgeführt werden:

#include <iostream>

constexpr int square(int n) {
    return n * n;
}

int main() {
    constexpr int compileTime = square(5);  // Zur Kompilierzeit ausgewertet
    
    int x = 7;
    int runtime = square(x);  // Zur Laufzeit ausgewertet
    
    std::cout << compileTime << "\n";  // 25
    std::cout << runtime << "\n";      // 49
}

Wenn Sie eine Auswertung zur Kompilierzeit garantieren müssen, verwenden Sie consteval. Eine consteval-Funktion muss eine Konstante erzeugen – sie mit Laufzeitwerten aufzurufen, ist ein Kompilierfehler:

consteval int factorial(int n) {
    return n <= 1 ? 1 : n * factorial(n - 1);
}

int main() {
    constexpr int result = factorial(5);  // OK: 120 zur Kompilierzeit berechnet
    
    // int x = 5;
    // int bad = factorial(x);  // FEHLER: x ist keine Konstante
}

Sie können constexpr auch mit Variablen und sogar Klassenkonstruktoren verwenden, was es ermöglicht, ganze Objekte zur Kompilierzeit zu erstellen. Dies ist besonders nützlich für Lookup-Tabellen, Konfigurationswerte oder alle Daten, die sich während der Programmausführung nicht ändern.

challenge icon

Aufgabe

Einfach

Sie werden Ihren Code in drei Dateien organisieren:

  • MathUtils.h: Definieren Sie Ihre mathematischen Funktionen für die Kompilierzeit.

    Erstellen Sie die folgenden Funktionen:

    • cube — eine constexpr-Funktion, die ein int entgegennimmt und dessen Kubikzahl (n * n * n) zurückgibt.
    • triangularNumber — eine constexpr-Funktion, die die n-te Dreieckszahl mit der Formel n * (n + 1) / 2 berechnet. In dieser Aufgabe rufen wir sie nur im Kompilierzeit-Kontext auf und speichern ihr Ergebnis in einer constexpr-Variablen.
    • sumOfSquares — eine constexpr-Funktion, die zwei Ganzzahlen entgegennimmt und die Summe ihrer Quadrate (a*a + b*b) zurückgibt.
  • Config.h: Erstellen Sie eine Konfigurationsstruktur unter Verwendung von Kompilierzeit-Konstanten.

    Definieren Sie ein Config-Struct mit einem constexpr-Konstruktor, der drei Ganzzahlen entgegennimmt: width, height und depth. Speichern Sie diese als öffentliche Member. Fügen Sie außerdem eine constexpr-Methode namens volume() hinzu, die width * height * depth zurückgibt.

    Erstellen Sie unterhalb des Structs eine globale constexpr-Konstante namens DEFAULT_CONFIG, die mit den Werten 10, 20 und 5 initialisiert wird.

  • main.cpp: Lesen Sie zwei Ganzzahlen von der Eingabe ein, die Laufzeitwerte darstellen.

    Demonstrieren Sie zunächst die Auswertung zur Kompilierzeit, indem Sie constexpr-Variablen erstellen:

    • Speichern Sie cube(4) in einer constexpr-Variablen und geben Sie aus: Cube of 4: [value]
    • Speichern Sie triangularNumber(10) in einer constexpr-Variablen und geben Sie aus: 10th triangular number: [value]
    • Geben Sie das Volumen der Standardkonfiguration aus: Default volume: [value]

    Demonstrieren Sie dann, dass constexpr-Funktionen auch zur Laufzeit funktionieren können, indem Sie Ihre beiden Eingabewerte verwenden:

    • Rufen Sie cube() mit der ersten Eingabe auf und geben Sie aus: Cube of [input]: [result]
    • Rufen Sie sumOfSquares() mit beiden Eingaben auf und geben Sie aus: Sum of squares: [result]

Zum Beispiel mit den Eingaben 3 und 4:

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 3: 27
Sum of squares: 25

Mit den Eingaben 5 und 12:

Cube of 4: 64
10th triangular number: 55
Default volume: 1000
Cube of 5: 125
Sum of squares: 169

Probier es selbst

#include <iostream>
#include "MathUtils.h"
#include "Config.h"

using namespace std;

int main() {
    // Zwei Ganzzahlen von der Eingabe lesen
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Auswertung zur Kompilierzeit demonstrieren
    // Erstelle eine constexpr-Variable, die cube(4) speichert, und gib aus: "Cube of 4: [value]"
    
    // TODO: Erstelle eine constexpr-Variable, die triangularNumber(10) speichert
    // und gib aus: "10th triangular number: [value]"
    
    // TODO: Gib das Standardvolumen der Konfiguration aus: "Default volume: [value]"
    
    // TODO: Demonstriere die Laufzeitnutzung von constexpr-Funktionen
    // Rufe cube() mit input1 auf und gib aus: "Cube of [input1]: [result]"
    
    // TODO: Rufe sumOfSquares() mit beiden Eingaben auf
    // und gib aus: "Sum of squares: [result]"
    
    return 0;
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung