constexpr (C++)
Le mot clé constexpr
a été introduit en C++11 et amélioré en C++14. Cela signifie constune expression dente. Comme const
, il peut être appliqué à des variables : une erreur du compilateur est déclenchée quand un code tente de modify la valeur. Contrairement const
à , constexpr
peut également être appliqué aux fonctions et aux ructoraux de classe const. constexpr
indique que la valeur ou la valeur de retour est constdente et, dans la cas possible, est calculée au moment de la compilation.
Une constexpr
valeur intégrale peut être utilisée partout où un const entier est requis, par exemple dans les arguments de modèle et les déclarations de tableau. Et lorsqu’une valeur est calculée au moment de la compilation au lieu de l’exécution, elle permet à votre programme d’exécuter plus rapidement et d’utiliser moins de mémoire.
Pour limiter la complexité des calculs d’ant au moment constde la compilation et leur impact potentiel sur le temps de compilation, la norme C++14 exige que les types d’expressions constant soient des types littérals.
Syntaxe
constexpr
ident de typelittéral ier=constant-expression ;if
constexpr
ident de typelittéral ier{ant-expressionconst} ;if
constexpr
ident de typelittéral ier(params) ;if
constexpr
ctor(params) ;
Paramètres
params
Un ou plusieurs paramètres, dont chacun doit être un type littéral et doit lui-même être une constexpression dent.
Valeur retournée
Une constexpr
variable ou une fonction doit retourner un type littéral.
Variables constexpr
La référence difprincipale entre const
les constexpr
variables est que l’initialisation d’une const
variable peut être différée jusqu’au moment de l’exécution. Une constexpr
variable doit être initialisée au moment de la compilation. Toutes les constexpr
variables sont const
.
Une variable peut être déclarée avec
constexpr
, lorsqu’elle a un type littéral et est initialisée. Si l’initialisation est effectuée par unforconst ructoreur, le constructor doit être déclaré commeconstexpr
.Une référence peut être déclarée comme
constexpr
lorsque ces deux conditions sont remplies : l’objet référencé est initialisé par une constexpression ant et toutes les conversions implicites appelées pendant l’initialisation sont également constdes expressions dent.Toutes les déclarations d’une variable ou d’une
constexpr
fonction doivent avoir laconstexpr
spécificationifplus grande.
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
fonctionsconstexpr
Une constexpr
fonction est une fonction dont la valeur de retour est computable au moment de la compilation lorsque le code le nécessite. Le code consommant nécessite la valeur de retour au moment de la compilation pour initialiser une constexpr
variable ou pour fournir un argument de modèle non de type. Lorsque ses arguments sont constexpr
des valeurs, une constexpr
fonction produit une fourmi au moment constde la compilation. Lorsqu’elle est appelée avec des arguments nonconstexpr
arguments ou si sa valeur n’est pas requise au moment de la compilation, elle produit une valeur au moment de l’exécution comme une fonction régulière. (Ce comportement double vous permet d’avoir à écrire constexpr
et non desconstexpr
versions de la même fonction.)
Une constexpr
fonction ou constun ructorateur est implicitement inline
.
Les règles suivantes s’appliquent aux constexpr fonctions :
Une
constexpr
fonction doit accepter et retourner uniquement les types littéraux.Une
constexpr
fonction peut être récursive.Before C++20, une
constexpr
fonction ne peut pas être virtuelle et un constructoreur ne peut pas être défini commeconstexpr
lorsque la classe englobante a des classes de base virtuelles. En C++20 et versions ultérieures, uneconstexpr
fonction peut être virtuelle. Visual Studio 2019 version 16.10 et versions ultérieures prennent en chargeconstexpr
les fonctions virtuelles lorsque vous specezify l’option du/std:c++20
compilateur ou ultérieure.Le corps de la fonction peut être défini avec la valeur
= default
ou= delete
.Le corps ne peut contenir aucune
goto
instruction nitry
bloc.Une spécialisation explicite d’un modèle non-modèle
constexpr
peut être déclarée commeconstexpr
suit :Une spécialisation explicite d’un
constexpr
modèle n’a pas non plus besoin d’êtreconstexpr
:
Les règles suivantes s’appliquent aux constexpr
fonctions dans Visual Studio 2017 et versions ultérieures :
Il peut contenir et des instructions, ainsi que toutes les instructions de bouclage, y compris
for
, basées surfor
des plages,while
et do-while.if
switch
Il peut contenir des déclarations de variables locales, mais la variable doit être initialisée. Il doit s’agir d’un type littéral et ne peut pas être
static
ou thread-local. La variable déclarée localement n’est pas nécessaireconst
et peut muter.Une
constexpr
fonction non membrestatic
n’est pas nécessaire pour être implicitementconst
.
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;
}
Conseil
Dans le débogueur Visual Studio, lors du débogage d’une build de débogage non optimisée, vous pouvez indiquer si une constexpr
fonction est évaluée au moment de la compilation en y plaçant un point d’arrêt. Si le point d'arrêt est atteint, la fonction a été appelée à l'exécution. Sinon, la fonction a été appelée au moment de la compilation.
Extern constexpr
L’option du compilateur /Zc :externConstexpr entraîne l’application de la liaison externe aux variables déclarées à l’aide d’extern constexpr. Dans les versions antérieures de Visual Studio, soit par défaut, soit lorsque /Zc :externConstexpr- est spécifiéif, Visual Studio applique une liaison interne aux constexpr
variables même lorsque le extern
mot clé est utilisé. L’option /Zc :externConstexpr est disponible à partir de Visual Studio 2017 Update 15.6 et est désactivée par défaut. L’option /permissive- n’active pas /Zc :externConstexpr.
Exemple
L’exemple suivant montre des constexpr
variables, des fonctions et un type défini par l’utilisateur. Dans la dernière instruction dans main()
, la constexpr
fonction GetValue()
membre est un appel au moment de l’exécution, car la valeur n’est pas requise pour être connue au moment de la compilation.
// 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;
}
Spécifications
Visual Studio 2015 ou version ultérieure.
Voir aussi
Commentaires
https://aka.ms/ContentUserFeedback.
Bientôt disponible : Tout au long de 2024, nous allons supprimer progressivement GitHub Issues comme mécanisme de commentaires pour le contenu et le remplacer par un nouveau système de commentaires. Pour plus d’informations, consultezEnvoyer et afficher des commentaires pour