constexpr (C++)

Die Schlüsselwort (keyword) constexpr wurde in C++11 eingeführt und in C++14 verbessert. Dies bedeutet constant-Ausdruck. Wie constkann es auf Variablen angewendet werden: Ein Compilerfehler wird ausgelöst, wenn code versucht, den Wert zu modierenif. constexpr Im Gegensatz dazu constkönnen auch Funktionen und Klassen-Ructors constangewendet werden. constexpr gibt an, dass der Wert oder der Rückgabewert ant und const, sofern möglich, zur Kompilierungszeit berechnet wird.

Ein constexpr integraler Wert kann überall verwendet werden, wo eine const ganze Zahl erforderlich ist, z. B. in Vorlagenargumenten und Arraydeklarationen. Und wenn ein Wert zur Kompilierungszeit anstelle der Laufzeit berechnet wird, hilft es Ihrem Programm, schneller zu laufen und weniger Arbeitsspeicher zu verwenden.

Um die Komplexität von Kompilierungszeit-Ant-Berechnungen und deren potenzielle Auswirkungen auf die Kompilierungszeit zu begrenzen, benötigt der C++14-Standard constdie Typen in constAnt-Ausdrücken als Literaltypen.

Syntax

constexprliteral-type ident ier=constant-expression;if
constexprliteral-typeidentifier{constant-expression};
constexprliteral-typeidentifier(params);
constexprctor(params);

Parameter

params
Mindestens ein Parameter, von denen jeder literaltyp sein muss und selbst ein constAnt-Ausdruck sein muss.

Rückgabewert

Eine constexpr Variable oder Funktion muss einen Literaltyp zurückgeben.

constexpr-Variablen

Die primäreifD-Ference zwischen const und constexpr Variablen besteht darin, dass die Initialisierung einer const Variablen bis zur Laufzeit zurückgestellt werden kann. Eine constexpr Variable muss zur Kompilierungszeit initialisiert werden. Alle constexpr Variablen sind const.

  • Eine Variable kann mit constexpreinem Literaltyp deklariert und initialisiert werden. Wenn die Initialisierung von einem constRuctor proforMed erfolgt, muss der constRuctor als constexprdeklariert werden.

  • Ein Verweis kann so deklariert werden, als constexpr wenn beide Bedingungen erfüllt sind: Das referenzierte Objekt wird durch einen constAntausdruck initialisiert, und alle impliziten Konvertierungen, die während der Initialisierung aufgerufen werden, sind ebenfalls constAnt-Ausdrücke.

  • Alle Deklarationen einer constexpr Variablen oder Funktion müssen die constexpr Spezifikationifier aufweisen.

constexpr float x = 42.0;
constexpr float y{108};
constexpr float z = exp(5, 3);
constexpr int i; // Error! Not initialized
int j = 0;
constexpr int k = j + 1; //Error! j not a constant expression

constexpr-Funktionen

Eine constexpr Funktion ist eine Funktion, deren Rückgabewert zur Kompilierungszeit bei Verwendung von Code erforderlich ist. Der Verbrauch von Code erfordert den Rückgabewert zur Kompilierungszeit, um eine constexpr Variable zu initialisieren oder ein Nicht-Typ-Vorlagenargument bereitzustellen. Wenn es sich bei den Argumenten constexpr um Werte handelt, erzeugt eine constexpr Funktion eine Kompilierungszeit-Ant const. Wenn sie mit nicht-Argumentenconstexpr aufgerufen wird oder der Wert zur Kompilierungszeit nicht erforderlich ist, erzeugt sie zur Laufzeit einen Wert wie eine normale Funktion. (Mit diesem dualen Verhalten können Sie keine Versionen derselben Funktion schreiben constexpr und nichtconstexpr verwenden.)

Eine Funktion oder constein constexpr Ructor ist implizit inline.

Die folgenden Regeln gelten für constexpr Funktionen:

  • Eine constexpr Funktion muss nur Literaltypen akzeptieren und zurückgeben.

  • Eine constexpr Funktion kann rekursiv sein.

  • Seifore C++20, eine constexpr Funktion kann nicht virtuell sein, und ein constRuctor kann nicht so definiert werden, constexpr als wenn die eingeschlossene Klasse über virtuelle Basisklassen verfügt. In C++20 und höher kann eine constexpr Funktion virtuell sein. Visual Studio 2019, Version 16.10 und höher, unterstützen constexpr virtuelle Funktionen, wenn Sie die /std:c++20 Compileroption oder höher festlegenif.

  • Der Text kann als = default oder = delete definiert werden.

  • Der Textkörper kann keine goto Anweisungen oder try Blöcke enthalten.

  • Eine explizite Spezialisierung einer Nicht-Vorlageconstexpr kann wie constexprfolgt deklariert werden:

  • Eine explizite Spezialisierung einer constexpr Vorlage muss nicht auch sein constexpr:

Die folgenden Regeln gelten für constexpr Funktionen in Visual Studio 2017 und höher:

  • Es kann Anweisungen und switch Anweisungen sowie alle Schleifenanweisungen enthaltenif, einschließlich for, bereichsbasiert for, whileund do-while.

  • Sie kann lokale Variablendeklarationen enthalten, die Variable muss jedoch initialisiert werden. Er muss ein Literaltyp sein und darf nicht lokal sein static . Die lokal deklarierte Variable ist nicht erforderlich und kann mutiert werden const.

  • Eine constexpr Nicht-Member-Funktionstatic ist nicht implizit consterforderlich.

constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

Tipp

Im Visual Studio-Debugger können Sie beim Debuggen eines nicht optimierten Debugbuilds feststellen, ob eine constexpr Funktion zur Kompilierungszeit ausgewertet wird, indem Sie einen Haltepunkt darin einfügen. Wenn der Haltepunkt erreicht wird, wurde die Funktion zur Laufzeit aufgerufen. Wenn dies nicht der Fall ist, wurde die Funktion zum Zeitpunkt der Kompilierung aufgerufen.

extern constexpr

Die Compileroption /Zc:externConstexpr bewirkt, dass der Compiler externe Verknüpfungen auf Variablen anwendet, die mithilfe von extern constexprdeklariert werden. In früheren Versionen von Visual Studio, entweder standardmäßig oder wenn /Zc:externConstexpr- angegebenifist, wendet Visual Studio interne Verknüpfungen auf constexpr Variablen an, auch wenn die extern Schlüsselwort (keyword) verwendet wird. Die Option "/Zc:externConstexpr " ist ab Visual Studio 2017 Update 15.6 verfügbar und ist standardmäßig deaktiviert. Die Option "/permissive" aktiviert nicht /Zc:externConstexpr.

Beispiel

Das folgende Beispiel zeigt constexpr Variablen, Funktionen und einen benutzerdefinierten Typ. In der letzten Anweisung in main()der constexpr Memberfunktion GetValue() handelt es sich um einen Laufzeitaufruf, da der Wert zur Kompilierungszeit nicht bekannt sein muss.

// constexpr.cpp
// Compile with: cl /EHsc /W4 constexpr.cpp
#include <iostream>

using namespace std;

// Pass by value
constexpr float exp(float x, int n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp(x * x, n / 2) :
        exp(x * x, (n - 1) / 2) * x;
}

// Pass by reference
constexpr float exp2(const float& x, const int& n)
{
    return n == 0 ? 1 :
        n % 2 == 0 ? exp2(x * x, n / 2) :
        exp2(x * x, (n - 1) / 2) * x;
}

// Compile-time computation of array length
template<typename T, int N>
constexpr int length(const T(&)[N])
{
    return N;
}

// Recursive constexpr function
constexpr int fac(int n)
{
    return n == 1 ? 1 : n * fac(n - 1);
}

// User-defined type
class Foo
{
public:
    constexpr explicit Foo(int i) : _i(i) {}
    constexpr int GetValue() const
    {
        return _i;
    }
private:
    int _i;
};

int main()
{
    // foo is const:
    constexpr Foo foo(5);
    // foo = Foo(6); //Error!

    // Compile time:
    constexpr float x = exp(5, 3);
    constexpr float y { exp(2, 5) };
    constexpr int val = foo.GetValue();
    constexpr int f5 = fac(5);
    const int nums[] { 1, 2, 3, 4 };
    const int nums2[length(nums) * 2] { 1, 2, 3, 4, 5, 6, 7, 8 };

    // Run time:
    cout << "The value of foo is " << foo.GetValue() << endl;
}

Anforderungen

Visual Studio 2015 oder eine höhere Version.

Siehe auch

Deklarationen und Definitionen
const