Quelle est la différence entre et
?
- Quand est-ce que je peux utiliser une seule d'entre elles ?
- Quand puis-je utiliser tous les deux et Comment devrais-je choisir un ?
Quelle est la différence entre et
?
Les deux mots clés peuvent être utilisés dans la déclaration des objets ainsi que des fonctions. La différence fondamentale lorsqu'il est appliqué à des objets est ceci:
const
déclare un objet en tant que constante. Cela implique une garantie que, une fois initialisé, la valeur de l'objet ne change pas, et le compilateur peut utiliser ce fait pour faire des optimisations. Il permet également d'éviter au programmeur d'écrire le code qui modifie les objets qui n'étaient pas destinés à être modifiés après l'initialisation.
constexpr
déclare un objet comme à une utilisation à ce que la Norme appelle des expressions constantes. Mais notez que l' constexpr
n'est pas la seule façon de le faire.
Lorsqu'il est appliqué à des fonctions de la différence de base est ceci:
const
ne peuvent être utilisés que pour des fonctions membres statiques, pas de fonctions en général. Il donne une garantie que la fonction de membre de ne pas modifier les non-membres de données statiques.
constexpr
peut être utilisée à la fois membre et non-membre de fonctions, que bien des constructeurs. Il déclare la fonction d'ajustement pour les utiliser dans des expressions constantes. Le compilateur ne l'accepter que si la fonction répond à certains critères (7.1.5/3,4), le plus important (†):
return
déclaration est autorisé. Dans le cas d'un constructeur, seulement une liste d'initialisation, typedefs et statique affirmer sont autorisés. (= default
et = delete
sont permis, aussi, si.)Comme dit ci-dessus, constexpr
déclare à la fois des objets ainsi que des fonctions aptes à être utilisés dans des expressions constantes. Une expression constante est plus que simplement de la constante:
Il peut être utilisé dans des endroits qui nécessitent de la compilation d'évaluation, par exemple, des paramètres de modèle et la matrice de taille prescripteurs:
template <int N>
class fixed_size_list
{ /*...*/ };
fixed_size_list<X> mylist; // <-- X must be an integer constant expression
int numbers[X]; // <-- X must be an integer constant expression
Mais attention:
Déclarer que quelque chose comme constexpr
ne garantit pas nécessairement qu'il sera évalué au moment de la compilation. Il peut être utilisé pour un tel, mais il peut être utilisé dans d'autres endroits qui sont évalués au moment de l'exécution, ainsi.
Un objet peut être adapté pour une utilisation dans des expressions constantes , sans être déclaré constexpr
. Exemple:
int main() {
const int N = 3;
int numbers[N] = { 1 , 2, 3 }; // <-- N is constant expression
/*...*/
}
Cela est possible parce qu' N
, être constant et initialisé au moment de la déclaration avec un littéral, satisfait aux critères d'une expression constante, même si elle n'est pas déclarée constexpr
.
Quand donc en fait, j'ai utiliser constexpr
?
Un objet comme N
ci-dessus peut être utilisé comme expression constante sans être déclaré constexpr
. Cela est vrai pour tous les objets qui sont:
const
[Ceci est dû au §5.19/2: Une constante de l'expression ne doit pas inclure les sous-expressions qui implique "une lvalue-à-rvalue modification, sauf si [...] un glvalue de l'intégrale ou type d'énumération [...]". Merci à Richard Smith pour la correction de mes revendication précédente que c'était vrai pour tous littérale types]
Pour une fonction à être utilisé dans des expressions constantes, il doit être explicitement déclarée constexpr
; il n'est pas suffisant pour simplement satisfaire aux critères d'constante de l'expression des fonctions. Exemple:
template <int N>
class list
{ };
constexpr int sqr1(int arg)
{ return arg*arg; }
int sqr2(int arg)
{ return arg*arg; }
int main()
{
const int X = 2;
list<sqr1(X)> mylist1; // OK; sqr1 is constexpr
list<sqr2(X)> mylist2; // Wrong; sqr2 is not constexpr
return 0;
}
Quand puis-je / dois-je utiliser les deux, const
et constexpr
ensemble?
a) Dans l'objet de déclarations , Ce n'est jamais nécessaire lorsque les deux mots-clés renvoient à l'objet même d'être déclarée. constexpr
implique const
.
constexpr const int N = 5;
est le même que
constexpr int N = 5;
Toutefois, notez qu'il peut y avoir des situations où les mots clés de chaque désigner les différentes parties de la déclaration:
static constexpr int N = 3;
int main()
{
constexpr const int *NP = &N;
return 0;
}
Ici, NP
est déclarée comme une adresse constante de l'expression, c'est à dire un pointeur qui est elle-même une expression constante. (Ce qui est possible lorsque l'adresse est généré par l'application de l'adresse de l'opérateur statique/global d'expression constante.) Ici, les deux constexpr
et const
sont requis: constexpr
toujours se réfère à l'expression d'être déclaré (ici NP
), tandis que l' const
désigne int
(il déclare un pointeur-à-const). Retrait de l' const
rendrait l'expression illégales (parce que (a) un pointeur vers un non-const objet ne peut pas être une expression constante et (b) &N
est en fait un pointeur vers une constante).
b) En fonction de membre de déclarations En C++11, constexpr
implique const
également pour les fonctions de membres. Cependant, il est susceptible de changer en C++14. Selon les projets actuels, constexpr
implique const
seulement pour les objets, pas pour les fonctions de membre, en raison d'un changement proposé au §7.1.5/8. Par conséquent, un membre de la fonction déclarée en vertu de C++11
constexpr void f();
devront être déclarées comme
constexpr void f() const;
en vertu de C++14, de manière à toujours être utilisable en tant que const
fonction. Meilleur marque de votre constexpr
fonctions de membre en tant que const
, même maintenant, de manière à éviter d'avoir à changer beaucoup de code plus tard.
(†) Les conditions d'acceptabilité de la constexpr
fonctions seront probablement détendu pour le C++14. Une proposition de Richard Smith a récemment été adoptée dans le C++14 projet.
const
s'applique pour les variables, et les empêche d'être modifié dans votre code.
constexpr
indique au compilateur que cette expression des résultats dans un moment de la compilation, la valeur de la constante, de sorte qu'il peut être utilisé dans des endroits comme la matrice des longueurs, l'attribution d' const
variables, etc. Le lien donné par Oli a un grand nombre d'excellents exemples.
Essentiellement, ils sont 2 concepts différents en tout, et peuvent (et doivent) être utilisés ensemble.
Selon le livre "Le Langage de Programmation C++ 4ème Édition" par Bjarne Stroustrup
• const: ce qui signifie à peu près ‘je promets de ne pas modifier cette valeur" (§7.5). Ceci est utilisé principalement
pour spécifier des interfaces, de sorte que les données peuvent être transmises à des fonctions sans crainte d'être modifiée.
Le compilateur applique à la promesse faite par const.
• constexpr: ce qui signifie à peu près ‘pour être évaluée au moment de la compilation" (§10.4). C'est principalement utilisé pour spécifier des constantes, afin de permettre
Par exemple:
const int dmv = 17; // dmv is a named constant
int var = 17; // var is not a constant
constexpr double max1 = 1.4*square(dmv); // OK if square(17) is a constant expression
constexpr double max2 = 1.4∗square(var); // error : var is not a constant expression
const double max3 = 1.4∗square(var); //OK, may be evaluated at run time
double sum(const vector<double>&); // sum will not modify its argument (§2.2.5)
vector<double> v {1.2, 3.4, 4.5}; // v is not a constant
const double s1 = sum(v); // OK: evaluated at run time
constexpr double s2 = sum(v); // error : sum(v) not constant expression
Pour une fonction soit utilisable dans une expression constante, qui est, dans une expression qui sera évaluée
par le compilateur, il doit être défini constexpr.
Par exemple:
constexpr double square(double x) { return x∗x; }
Pour être constexpr, une fonction doit être plutôt simple: juste un retour-déclaration de calcul d'une valeur. Un
constexpr fonction peut être utilisée pour les non-constante des arguments, mais quand c'est fait, le résultat n'est pas un
expression constante. Nous permettons à un constexpr fonction qui doit être appelée avec des non-constante-l'expression des arguments
dans des contextes qui ne nécessitent pas des expressions constantes, de sorte que nous n'avons pas le vha e pour définir essentiellement
la même fonction deux fois: une fois pour les expressions constantes et une fois pour les variables.
Dans quelques endroits, des expressions constantes sont requis par les règles de la langue (p. ex., les limites du tableau (§2.2.5,
§7.3), les étiquettes de caisse (§2.2.4, §9.4.2), certains arguments de modèle (§25.2), et les constantes déclarées à l'aide de
constexpr). Dans d'autres cas, au moment de la compilation d'évaluation est important pour la performance. Indépendamment de
les problèmes de performance, la notion de l'immuabilité (d'un objet avec une immuable de l'état) est un
de conception important sujet de préoccupation (§10.4).
Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.