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 Leistung erheblich verbessern kann. Das Schlüsselwort constexpr (C++11) und das Schlüsselwort consteval (C++20) geben dir Kontrolle darüber, wann Ausdrücke ausgewertet werden.

Eine constexpr-Funktion kann zur Kompilierzeit ausgewertet werden, wenn ihr konstante Argumente übergeben werden, sie kann aber 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 du die Auswertung zur Kompilierzeit garantieren musst, verwende consteval. Eine consteval-Funktion muss eine Konstante erzeugen – sie mit Laufzeitwerten aufzurufen, führt zu einem Kompilierungsfehler:

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

int main() {
    constexpr int result = factorial(5);  // OK: 120 zur Compile-Zeit berechnet
    
    // int x = 5;
    // int bad = factorial(x);  // ERROR: x ist keine Konstante
}

Du kannst constexpr auch mit Variablen und sogar Klassenkonstruktoren verwenden, wodurch ganze Objekte zur Kompilierzeit erstellt werden können. Dies ist besonders nützlich für Nachschlagetabellen, Konfigurationswerte oder Daten, die sich während der Programmausführung nicht ändern.

challenge icon

Aufgabe

Einfach

Du organisierst deinen Code über drei Dateien:

  • MathUtils.h: Definiere deine Mathematikfunktionen zur Compile-Zeit.

    Erstelle die folgenden Funktionen:

    • cube: eine constexpr-Funktion, die ein int entgegennimmt und dessen Kubikzahl zurückgibt (n * n * n)
    • triangularNumber: eine constexpr-Funktion, die die n-te Dreieckszahl mithilfe der Formel n * (n + 1) / 2 berechnet. In dieser Aufgabe rufen wir sie ausschließlich in einem Compile-Zeit-Kontext auf und speichern ihr Ergebnis in einer constexpr-Variablen.
    • sumOfSquares: eine constexpr-Funktion, die zwei Ganzzahlen entgegennimmt und die Summe ihrer Quadrate zurückgibt (a*a + b*b)
  • Config.h: Erstelle eine Konfigurationsstruktur mit Konstanten zur Compile-Zeit.

    Definiere eine Config-Struktur mit einem constexpr-Konstruktor, der drei Ganzzahlen entgegennimmt: width, height und depth. Speichere diese als öffentliche Member. Füge außerdem eine constexpr-Methode namens volume() hinzu, die width * height * depth zurückgibt.

    Erstelle unterhalb der Struktur eine globale constexpr-Konstante namens DEFAULT_CONFIG, die mit den Werten 10, 20 und 5 initialisiert wird.

  • main.cpp: Lies zwei Ganzzahlen aus der Eingabe ein, die Laufzeitwerte darstellen.

    Zeige zunächst die Auswertung zur Compile-Zeit, indem du constexpr-Variablen erstellst:

    • Speichere cube(4) in einer constexpr-Variablen und gib Folgendes aus: Cube of 4: [value]
    • Speichere triangularNumber(10) in einer constexpr-Variablen und gib Folgendes aus: 10th triangular number: [value]
    • Gib das Volumen der Standardkonfiguration aus: Default volume: [value]

    Zeige anschließend, dass constexpr-Funktionen auch zur Laufzeit funktionieren können, indem du deine beiden Eingabewerte verwendest:

    • Rufe cube() mit der ersten Eingabe auf und gib Folgendes aus: Cube of [input]: [result]
    • Rufe sumOfSquares() mit beiden Eingaben auf und gib Folgendes aus: Sum of squares: [result]

Zum Beispiel bei den Eingaben 3 und 4:

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

Bei 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() {
    // Lese zwei Ganzzahlen von der Eingabe
    int input1, input2;
    cin >> input1;
    cin >> input2;
    
    // TODO: Demonstriere die Auswertung zur Kompilierzeit
    // Erstelle eine constexpr-Variable, die cube(4) speichert, und gib aus: "Cube of 4: [value]"
    
    // TODO: Create a constexpr variable storing triangularNumber(10)
    // and print: "10th triangular number: [value]"
    
    // TODO: Print the default config's volume: "Default volume: [value]"
    
    // TODO: Demonstriere die Laufzeitverwendung von constexpr-Funktionen
    // Rufe cube() mit input1 auf und gib aus: "Cube of [input1]: [result]"
    
    // TODO: Call sumOfSquares() with both inputs
    // and print: "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

Übe selbstständig: Online-C++-Compiler