constexpr (C++)
Klíčové slovo constexpr
bylo zavedeno v jazyce C++11 a vylepšeno v jazyce C++14. To znamená constvýraz ant. Podobně jako const
u proměnných se dá použít: Při každém pokusu o modifikováníifhodnoty se vyvolá chyba kompilátoru. Na rozdíl od const
, constexpr
lze také použít na funkce a ructory třídy const. constexpr
označuje, že hodnota nebo návratová hodnota je constant a pokud je to možné, vypočítá se v době kompilace.
constexpr
Celočíselnou hodnotu lze použít všude, kde const je požadováno celé číslo, například v argumentech šablony a deklarací pole. A když se hodnota vypočítá v době kompilace místo doby běhu, pomůže vašemu programu běžet rychleji a využívat méně paměti.
Aby se omezila složitost výpočtů v době constkompilace a jejich potenciální dopady na čas kompilace, standard C++14 vyžaduje, aby typy ve constvýrazech ant byly literální typy.
Syntaxe
constexpr
literal-typeidentifier=constant-expression;
constexpr
literal-typeidentifier{constant-expression};
constexpr
literal-typeidentifier(params);
constexpr
ctor(params);
Parametry
params
Jeden nebo více parametrů, z nichž každý musí být literálový typ a musí být sám výrazem constant.
Vrácená hodnota
Proměnná constexpr
nebo funkce musí vracet typ literálu.
constexpr Proměnné
Primární difference mezi const
proměnnými a constexpr
proměnnými spočívá v tom, že inicializace const
proměnné může být odložena do doby běhu. Proměnná constexpr
musí být inicializována v době kompilace. Všechny constexpr
proměnné jsou const
.
Proměnnou lze deklarovat pomocí
constexpr
, pokud má typ literálu a je inicializován. Pokud je inicializace performed ructor const, constmusí být ructor deklarován jakoconstexpr
.Odkaz může být deklarován, jako
constexpr
když jsou splněny obě tyto podmínky: Odkazovaný objekt je inicializován výrazem constant a všechny implicitní převody vyvolané během inicializace jsou také constant výrazy.Všechny deklarace
constexpr
proměnné nebo funkce musí mítconstexpr
specifikátorif.
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 – funkce
Funkce constexpr
je funkce, jejíž návratová hodnota je v době kompilace kompuovat, když ho vyžaduje náročný kód. Použití kódu vyžaduje návratovou hodnotu v době kompilace k inicializaci constexpr
proměnné nebo k poskytnutí argumentu šablony bez typu. Pokud jsou constexpr
argumenty hodnoty, constexpr
funkce vytvoří ant času constkompilace. Při zavolání s neconstexpr
argumenty nebo když není její hodnota v době kompilace nutná, vytvoří hodnotu za běhu, jako je běžná funkce. (Toto duální chování vás šetří od nutnosti psát constexpr
a neverzeconstexpr
stejné funkce.)
Funkce constexpr
nebo constructor je implicitně inline
.
Následující pravidla platí pro constexpr funkce:
constexpr
Funkce musí přijímat a vracet pouze literály.constexpr
Funkce může být rekurzivní.Before C++20,
constexpr
funkce nemůže být virtuální a constructor nelze definovat, jakoconstexpr
když má nadřazená třída všechny virtuální základní třídy. V jazyce C++20 a novějšíconstexpr
může být funkce virtuální. Visual Studio 2019 verze 16.10 a novější verze podporujíconstexpr
virtuální funkce, když specifikujeteifmožnost kompilátoru/std:c++20
nebo novější.Tělo může být definováno jako
= default
nebo= delete
.Tělo nesmí obsahovat žádné
goto
příkazy anitry
bloky.Explicitní specializace jiné
constexpr
šablony může být deklarována taktoconstexpr
:Explicitní specializace
constexpr
šablony nemusí býtconstexpr
také:
Následující pravidla platí pro constexpr
funkce v sadě Visual Studio 2017 a novější:
Může obsahovat
if
aswitch
příkazy a všechny příkazy smyčky, včetněfor
příkazů založených nafor
while
rozsahu a do-while.Může obsahovat deklarace místních proměnných, ale proměnná musí být inicializována. Musí to být literálový typ a nesmí být
static
místní nebo vlákno. Místně deklarovaná proměnná nemusí býtconst
a může ztlumit.constexpr
Nečlennástatic
funkce nemusí být implicitněconst
.
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;
}
Tip
Při ladění neoptimalovaného sestavení Ladění v ladicím programu sady Visual Studio můžete zjistit, jestli se funkce v době kompilace vyhodnocuje, tím, že constexpr
do ní umístíte zarážku. Pokud je zarážka nalezena, funkce byla volána za běhu. Pokud ne, funkce byla volána v době kompilace.
Externí constexpr
Možnost kompilátoru /Zc:externConstexpr způsobí, že kompilátor použije externí propojení na proměnné deklarované pomocí extern constexpr. V dřívějších verzích sady Visual Studio buď ve výchozím nastavení, nebo když je parametr /Zc:externConstexpr- specifikovanýif, visual Studio použije interní propojení s constexpr
proměnnými i v případě, že extern
se použije klíčové slovo. Možnost /Zc:externConstexpr je dostupná od sady Visual Studio 2017 Update 15.6 a je ve výchozím nastavení vypnutá. Možnost /permissive- nepovoluje /Zc:externConstexpr.
Příklad
Následující příklad ukazuje constexpr
proměnné, funkce a uživatelem definovaný typ. V posledním příkazu v main()
členové constexpr
funkci GetValue()
je volání za běhu, protože hodnota nemusí být známa v době kompilace.
// 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;
}
Požadavky
Sada Visual Studio 2015 nebo novější.
Viz také
Váš názor
https://aka.ms/ContentUserFeedback.
Připravujeme: V průběhu roku 2024 budeme postupně vyřazovat problémy z GitHub coby mechanismus zpětné vazby pro obsah a nahrazovat ho novým systémem zpětné vazby. Další informace naleznete v tématu:Odeslat a zobrazit názory pro