Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
Słowo kluczowe constexpr zostało wprowadzone w języku C++11 i ulepszone w języku C++14.
Oznacza to wyrażenie stałe. Podobnie jak const, można go zastosować do zmiennych: podczas próby zmodyfikowania wartości jest zgłaszany błąd kompilatora. W przeciwieństwie do constklasy można constexpr również stosować do funkcji i konstruktorów klas.
constexpr wskazuje, że wartość lub wartość zwracana jest stała, a jeśli to możliwe, jest obliczana w czasie kompilacji.
Wartość constexpr całkowita może być używana wszędzie tam const , gdzie wymagana jest liczba całkowita, na przykład w argumentach szablonu i deklaracjach tablicy. A gdy wartość jest obliczana w czasie kompilacji zamiast czasu wykonywania, pomaga program działać szybciej i używać mniejszej ilości pamięci.
Aby ograniczyć złożoność obliczeń stałych w czasie kompilacji i ich potencjalny wpływ na czas kompilacji, standard C++14 wymaga typów w wyrażeniach stałych jako typów literałów.
Składnia
constexprtyp literałuwyrażenie-stałe identyfikatora= ;
constexprtyp literałuidentifier{constant-expression};
constexprtyp literałuidentifier(params);
constexprctor( params);
Parametry
params
Co najmniej jeden parametr, z których każdy musi być typem literału i musi być wyrażeniem stałym.
Wartość zwracana
Zmienna constexpr lub funkcja musi zwracać typ literału.
constexpr Zmiennych
Podstawową różnicą między zmiennymi const i constexpr jest to, że inicjowanie zmiennej const można odroczyć do czasu wykonywania. Zmienna constexpr musi być inicjowana w czasie kompilacji. Wszystkie constexpr zmienne to const.
Zmienną można zadeklarować za pomocą
constexprmetody , gdy ma typ literału i jest inicjowana. Jeśli inicjowanie jest wykonywane przez konstruktor, konstruktor musi być zadeklarowany jakoconstexpr.Odwołanie może być zadeklarowane tak, jak
constexprw przypadku spełnienia obu tych warunków: obiekt, do którego odwołuje się, jest inicjowany przez wyrażenie stałe, a wszelkie niejawne konwersje wywoływane podczas inicjowania są również wyrażeniami stałymi.Wszystkie deklaracje zmiennej
constexprlub funkcji muszą miećconstexprspecyfikator.
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, funkcje
Funkcja jest funkcją constexpr , której wartość zwracana jest komputable w czasie kompilacji, gdy wymaga jej użycie. Korzystanie z kodu wymaga wartości zwracanej w czasie kompilacji constexpr w celu zainicjowania zmiennej lub podania argumentu szablonu innego niż typ. Gdy argumenty są constexpr wartościami, constexpr funkcja generuje stałą czasu kompilacji. Gdy jest wywoływana z argumentami innym niżconstexpr argumenty lub gdy jej wartość nie jest wymagana w czasie kompilacji, generuje wartość w czasie wykonywania, jak zwykła funkcja. (To podwójne zachowanie pozwala zaoszczędzić na konieczności zapisu constexpr i innychconstexpr wersji tej samej funkcji).
Funkcja constexpr lub konstruktor jest niejawnie inline.
Następujące reguły dotyczą constexpr funkcji:
constexprFunkcja musi akceptować i zwracać tylko typy literałów.Funkcja
constexprmoże być rekursywna.Przed językiem
constexprC++20 funkcja nie może być wirtualna, a konstruktor nie może być zdefiniowany tak, jakconstexprw przypadku, gdy otaczającej klasy mają jakiekolwiek wirtualne klasy bazowe. W języku C++20 lub nowszym funkcja może być wirtualnaconstexpr. Program Visual Studio 2019 w wersji 16.10 lub nowszej obsługujeconstexprfunkcje wirtualne po określeniu lub nowszej opcji kompilatora/std:c++20.Treść można zdefiniować jako
= defaultlub= delete.Treść nie
gotomoże zawierać żadnych instrukcji anitrybloków.Jawna specjalizacja szablonu innego niż
constexprszablon można zadeklarować jakoconstexpr:Jawna specjalizacja szablonu
constexprnie musi być również :constexpr
Następujące reguły dotyczą constexpr funkcji w programie Visual Studio 2017 i nowszych wersjach:
Może zawierać
ifinstrukcje iswitchoraz wszystkie instrukcje pętli, w tymfor, oparte naforzakresie ,whilei do-while.Może zawierać deklaracje zmiennych lokalnych, ale zmienna musi zostać zainicjowana. Musi być typem literału i nie może być
staticani wątkowo-lokalny. Lokalnie zadeklarowana zmienna nie jest wymagana doconstwartości i może być mutacja.Funkcja
constexprniezwiązanastaticz elementem członkowskim nie musi być niejawnieconst.
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;
}
Napiwek
W debugerze programu Visual Studio podczas debugowania nieoptymalizowanej kompilacji debugowania można określić, czy constexpr funkcja jest oceniana w czasie kompilacji, umieszczając wewnątrz niej punkt przerwania. Jeśli punkt przerwania zostanie trafiony, funkcja została wywołana w czasie wykonywania. Jeśli nie, funkcja została wywołana w czasie kompilacji.
Extern constexpr
Opcja kompilatora /Zc:externConstexpr powoduje, że kompilator stosuje połączenie zewnętrzne do zmiennych zadeklarowanych przy użyciu extern constexpr. We wcześniejszych wersjach programu Visual Studio domyślnie lub po określeniu /Zc:externConstexpr program Visual Studio stosuje wewnętrzne powiązania ze constexpr zmiennymi nawet wtedy, gdy extern słowo kluczowe jest używane.
Opcja /Zc:externConstexpr jest dostępna począwszy od programu Visual Studio 2017 Update 15.6 i jest domyślnie wyłączona. Opcja /permissive- nie włącza /Zc:externConstexpr.
Przykład
W poniższym przykładzie przedstawiono constexpr zmienne, funkcje i typ zdefiniowany przez użytkownika. W ostatniej instrukcji w elemencie main()funkcja constexpr składowa GetValue() jest wywołaniem czasu wykonywania, ponieważ wartość nie jest wymagana, aby być znana w czasie kompilacji.
// 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;
}
Wymagania
Program Visual Studio 2015 lub nowszy.