Not
Åtkomst till den här sidan kräver auktorisering. Du kan prova att logga in eller ändra kataloger.
Åtkomst till den här sidan kräver auktorisering. Du kan prova att ändra kataloger.
Nyckelordet constexpr introducerades i C++11 och förbättrades i C++14. Det innebär konstant uttryck. Precis som constkan den tillämpas på variabler: Ett kompilatorfel utlöses när någon kod försöker ändra värdet. Till skillnad från constkan constexpr också tillämpas på funktioner och klasskonstruktorer.
constexpr anger att värdet, eller returvärdet, är konstant och om möjligt beräknas vid kompileringstillfället.
Ett constexpr integralvärde kan användas där ett const heltal krävs, till exempel i mallargument och matrisdeklarationer. Och när ett värde beräknas vid kompileringstid i stället för körning hjälper det ditt program att köras snabbare och använda mindre minne.
För att begränsa komplexiteten för kompileringstidskonstanta beräkningar och deras potentiella inverkan på kompileringstiden kräver C++14-standarden att typerna i konstanta uttryck är literaltyper.
Syntax
constexpridentifierare av literaltyp=konstantuttryck;
constexpridentifierare av literaltyp{konstantuttryck};
constexpridentifierare av literaltyp(params);
constexprctor(params);
Parametrar
params
En eller flera parametrar som var och en måste vara en literaltyp och måste vara ett konstant uttryck.
Returvärde
En constexpr variabel eller funktion måste returnera ett literalt värde av typen.
constexpr variabler
Den primära skillnaden mellan const och constexpr variabler är att initieringen av en const variabel kan skjutas upp till körningstiden. En constexpr variabel måste initieras vid kompileringen. Alla constexpr variabler är const.
En variabel kan deklareras med
constexpr, när den har en literaltyp och initieras. Om initieringen utförs av en konstruktor måste konstruktorn deklareras somconstexpr.En referens kan deklareras som
constexprnär båda dessa villkor uppfylls: Det refererade objektet initieras av ett konstant uttryck, och eventuella implicita konverteringar som anropas under initieringen är också konstanta uttryck.Alla deklarationer av en
constexprvariabel eller funktion måste haconstexpr-specificeraren.
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 funktioner
En constexpr-funktion är en funktion vars returvärde kan beräknas vid kompileringstid när det efterfrågas av koden. Användning av kod kräver returvärdet vid kompileringstillfället för att initiera en constexpr-variabel eller för att tillhandahålla ett icke-typ mallargument. När dess argument är constexpr värden skapar en constexpr-funktion en kompileringskonstant. När det anropas med argument som inteconstexpr, eller när dess värde inte krävs vid kompileringstillfället, genererar det ett värde vid körning som en vanlig funktion. (Det här dubbla beteendet sparar dig från att behöva skriva constexpr och icke-constexpr versioner av samma funktion.)
En constexpr funktion eller konstruktor är implicit inline.
Följande regler gäller för constexpr funktioner:
En
constexpr-funktion måste endast acceptera och returnera literaltyper.En
constexprfunktion kan vara rekursiv.Före C++20 kan en
constexpr-funktion inte vara virtuella, och en konstruktor kan inte definieras somconstexprnär den omslutande klassen har några virtuella basklasser. I C++20 och senare kan enconstexprfunktion vara virtuell. Visual Studio 2019 version 16.10 och senare versioner stöderconstexprvirtuella funktioner när du anger alternativet/std:c++20eller senare kompilator.Kroppen kan definieras som
= defaulteller= delete.Textkroppen får inte innehålla några
goto-instruktioner ellertry-block.En explicit specialisering av en mall som inte är
constexprkan deklareras somconstexpr:En explicit specialisering av en
constexprmall behöver inte heller varaconstexpr:
Följande regler gäller för constexpr funktioner i Visual Studio 2017 och senare:
Den kan innehålla
if- ochswitch-uttryck samt alla loop-satser, inklusivefor, intervallbaseradefor,whileoch do-while.Den kan innehålla lokala variabeldeklarationer, men variabeln måste initieras. Det måste vara en literaltyp och får inte vara
staticeller trådlokal. Den lokalt deklarerade variabeln måste inte varaconstoch kan mutera.En
constexpricke-staticmedlemsfunktion behöver inte vara implicitconst.
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;
}
Tips
När du felsöker en icke-optimerad felsökningsversion i Visual Studio-felsökningsprogrammet kan du se om en constexpr funktion utvärderas vid kompileringstidpunkten genom att placera en brytpunkt i den. Om brytpunkten träffas anropades funktionen under körning. Annars anropades funktionen vid kompileringstillfället.
extern constexpr
Alternativet /Zc:externConstexpr kompilator gör att kompilatorn tillämpar extern länkning på variabler som deklareras med hjälp av extern constexpr. I tidigare versioner av Visual Studio, antingen som standard eller när /Zc:externConstexpr– anges, tillämpar Visual Studio intern länkning på constexpr variabler även när nyckelordet extern används. Alternativet /Zc:externConstexpr är tillgängligt från och med Visual Studio 2017 Update 15.6 och är inaktiverat som standard. Alternativet /permissive- aktiverar inte /Zc:externConstexpr.
Exempel
I följande exempel visas constexpr variabler, funktioner och en användardefinierad typ. I den sista instruktionen i main()är funktionen constexpr medlem GetValue() ett körningsanrop eftersom värdet inte krävs för att vara känt vid kompileringstillfället.
// 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;
}
Krav
Visual Studio 2015 eller senare.