Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Das Schlüsselwort constexpr
wurde in C++11 eingeführt und in C++14 verbessert. Es bedeutet konstanter Ausdruck. Wie const
kann beispielsweise auf Variablen angewendet werden: Ein Compilerfehler wird ausgelöst, wenn ein Code versucht, den Wert zu ändern. Anders als const
, constexpr
kann auch auf Funktionen und Klassenkonstruktoren angewendet werden. constexpr
gibt an, dass der Wert oder Rückgabewert konstant ist und nach Möglichkeit zur Kompilierzeit berechnet wird.
Ein ganzzahliger constexpr
-Wert kann verwendet werden, wenn eine ganzzahlige const Konstante erforderlich ist, wie 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 konstanten Berechnungen zur Kompilierzeit und ihre potenziellen Auswirkungen auf die Kompilierungszeit zu begrenzen, verlangt der C++14-Standard, dass es sich bei den Typen in konstanten Ausdrücken um Literaltypen handelt .
Syntax
constexpr
LiteraltypBezeichner=konstantenausdruck;
constexpr
Literaltyp{Bezeichnerkonstantenausdruck};
constexpr
Bezeichner des Literaltyps(params);
constexpr
ctor(params);
Parameter
params
Einen oder mehrere Parameter, bei denen es sich jeweils um einen Literaltyp und einen konstanten Ausdruck handeln muss.
Rückgabewert
Eine constexpr
Variable oder Funktion muss einen Literaltypzurückgeben.
constexpr-Variablen
Der Hauptunterschied zwischen const
und constexpr
Variablen besteht darin, dass die Initialisierung einer const
Variablen bis zur Laufzeit verzögert werden kann. Eine constexpr
Variable muss zur Kompilierungszeit initialisiert werden. Alle constexpr
Variablen sind const
.
Eine Variable kann mit
constexpr
deklariert werden, wenn sie über einen Literaltyp verfügt und initialisiert wird. Wenn die Initialisierung von einem Konstruktor ausgeführt wird, muss der Konstruktor alsconstexpr
deklariert werden.Ein Verweis kann als
constexpr
deklariert werden, wenn diese beiden Bedingungen erfüllt sind: Das referenzierte Objekt wird durch einen konstanten Ausdruck initialisiert, und alle impliziten Umwandlungen, die während der Initialisierung aufgerufen werden, sind ebenfalls konstante Ausdrücke.Alle Deklarationen einer
constexpr
Variablen oder Funktion müssen über denconstexpr
Bezeichner verfügen.
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 um constexpr
Werte handelt, erzeugt eine constexpr
Funktion eine Kompilierzeitkonstante. Bei einem Aufruf mit Nicht-constexpr
-Argumenten, oder wenn der Wert nicht zum Zeitpunkt der Kompilierung erforderlich ist, wird ein Wert zur Laufzeit wie eine reguläre Funktion erzeugt. (Durch dieses duale Verhalten müssen Sie keine constexpr
- und Nicht-constexpr
-Versionen derselben Funktion schreiben.)
Eine constexpr
Funktion oder ein Konstruktor ist implizit inline
.
Für constexpr-Funktionen gelten die folgenden Regeln:
Eine
constexpr
-Funktion muss nur Literaltypen akzeptieren und zurückgeben.Eine
constexpr
-Funktion kann rekursiv sein.Vor C++20 kann eine
constexpr
Funktion nicht virtuell sein, und ein Konstruktor kann nicht alsconstexpr
definiert werden, wie wenn die einschließende Klasse über virtuelle Basisklassen verfügt. In C++20 und höher kann eineconstexpr
Funktion virtuell sein. Visual Studio 2019 Version 16.10 und höher unterstützenconstexpr
virtuelle Funktionen, wenn Sie die/std:c++20
Compileroption oder höher angeben.Der Text kann als
= default
oder= delete
definiert werden.Der Textkörper kann keine
goto
Anweisungen odertry
Blöcke enthalten.Eine explizite Spezialisierung einer Nicht-
constexpr
-Vorlage kann alsconstexpr
deklariert werden:Eine explizite Spezialisierung einer
constexpr
Vorlage muss nicht auchconstexpr
sein:
Die folgenden Regeln gelten für constexpr
Funktionen in Visual Studio 2017 und höher:
Sie kann
if
undswitch
Anweisungen sowie alle Schleifenanweisungen enthalten, einschließlichfor
, bereichsbasiertfor
,while
und do-while.Sie kann lokale Variablendeklarationen enthalten, die Variable muss jedoch initialisiert werden. Sie muss ein Literaltyp sein und darf nicht
static
oder thread-lokal sein. Die lokal deklarierte Variable muss nichtconst
sein und kann mutieren.Eine
constexpr
Nicht-Member-Funktionstatic
muss nicht implizitconst
sein.
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 nicht, wurde die Funktion während 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 wendet Visual Studio entweder standardmäßig oder wenn /Zc:externConstexpr- angegeben ist, die interne Verknüpfung auf constexpr
Variablen an, auch wenn das extern
Schlüsselwort 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 /Zc:externConstexpr nicht.
Beispiel
Das folgende Beispiel zeigt constexpr
-Variablen, -Funktionen und einen benutzerdefinierten Typ. In der letzten Anweisung in main()
ist die constexpr
Memberfunktion GetValue()
ein 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.