Difference/avantages de const et constexpr

Difference/avantages de const et constexpr

by Bassam El Rawas -
Number of replies: 3
Bonsoir,

J'ai dû définir dans le projet le nombre pi, et je l'ai déclaré avec const double PI = 3.14159... dans tools.cc (vu qu'il n'est pas utilisé autre part). 
Cependant, j'ai regardé le fichier constantes.h, dans lequel toutes les constantes sont définies avec constexpr. J'ai compris que const assure que la variable ne sera pas modifiée.
Par contre, je sais que constexpr signifie que la valeur de la variable est "connue a la compilation", et j'ai du mal a comprendre ce que cela veut dire, et pourquoi ceci n'est pas le cas pour les const (out même les autres types de variables). J'ai aussi du mal a voir les avantages de constexpr.

Merci d'avance c:
In reply to Bassam El Rawas

Re: Difference/avantages de const et constexpr

by Etienne Alain Jaroslav Salimbeni -

Salut , très bonne question

Alors oui dans ton cas de PI = 3.14 il se passe presque la même chose que tu utilises const ou constexpr.

L’intérêt de constexpr est de pouvoir faire le plus de calcul possible lors de la compilation et par conséquent gagner du temps lors de l’execution. Il devient alors très utile pour les expressions, ou des variables non littérales.

Par exemple si on définit la fonction f :

 constexpr int f(int a){

    return a+3+4/3*37%7;

}

int main(){

      f(25);

     return 0;

}

Dans ce programme, on ne perd pas de temps lors de son exécution pour calcuer f(25) car son resultat a déjà été fait lors de la compilation.

Une autre utilité de constexpr qui me vient a l’idée , est de tester le programme au moment de la compilation avec static_assert , ce qui permet d’empêcher la création de mauvais exécutables.  


J’espère avoir été clair

Il y a peut-être une autre raison  … , mais en générale constepr est utilise pour optimiser , alors que const est pour prévenir des erreurs.


In reply to Bassam El Rawas

Re: Difference/avantages de const et constexpr

by Jonas Samuel Daverio -

Bonsoir,

L'affirmation "connue à la compilation" veut dire que le compilateur connaît la valeur de la constante déjà au moment de la compilation. Pour comprendre pourquoi cela pourrait ne pas être le cas pour une constante, regarde cette exemple :

#include <iostream>

int main()

{
    int c_temp;
    std::cin >> c_temp;
    const int c(c_temp);

    //faire quelque chose avec c

   return 0;
}

Ici, on ne connaît pas la valeur de c_temp et par conséquent de c à la compilation, mais seulement à l'exécution (en effet, elle dépendra de l'entrée de l'utilisateur à cin). Si à la place de const int c, on avait déclaré constexpr int c(c_temp), on aurait eu une erreur de compilation car on ne peut pas initialiser un constexpr avec une variable (car on court le risque que sa valeur ne soit pas connue à la compilation, comme c'est le cas ici).

On utilise constexpr à chaque fois que l'on veut nommer une constante connue (comme π, par exemple). L'intérêt par rapport à un #define est que le compilateur peut toujours manipuler la valeur en contrôlant son type, alors qu'un #define "perd" le type. Pour plus de détails : https://stackoverflow.com/questions/42388077/constexpr-vs-macros.

Quant à l'optimisation, je ne suis pas convaincu. Le code d'Étienne Salimbeni serait optimisé par gcc si l'option -Ox suffisamment élevée est activée même si la fonction était déclaré int. D'une manière générale, gcc optimise toujours les expressions constantes même si elles ne sont pas déclarées explicitement constexpr. Je crois que l'intérêt de déclarer une variable constexpr et de s'assurer que la.e.s programmeuse.r.s utilise.nt bien l'expression de façon à ce qu'elle soit connue à la compilation.

Il y a toutefois apparemment quand même des situations où constexpr est nécessaire, par exemple avec static_assert, qui donnerait une erreur si const était utilisé à la place : https://stackoverflow.com/questions/13346879/const-vs-constexpr-on-variables . Ce que fait static_assert : https://stackoverflow.com/questions/1647895/what-does-static-assert-do-and-what-would-you-use-it-for
In reply to Jonas Samuel Daverio

Re: Difference/avantages de const et constexpr

by Etienne Alain Jaroslav Salimbeni -

Yep , t’as raison mon exemple était trop simple , même l’option -O1 exécute f lors de la compilation :/

Par contre si je prend un truc un peu plus farfelu comme :

constexpr int fib(int x) {

   if((x==1)||(x==0)) {

      return(x);

   }else {

      return(fib(x-1)+fib(x-2));

   }

}

 

L’option -O3 ne reconnait pas automatiquement cette fonction comme constexpr.

Si je veux optimiser le temps d’exécution , je dois y ajouter constexpr

 

Un autre exemple ou -O3 ne suffit pas serais la libraire standard algorithme , en effet depuis très peu ( C++20 ) presque toutes les fonctions sont devenu constexpr , ce qui veut dire que je peux trier mes donnes pendant la compilation et non l’exécution.