61 votes

constexpr vs const statique: lequel préférer?

Pour définir des constantes de compilation de l'ensemble des types comme suit (à la fonction et la portée de classe), dont la syntaxe est la meilleure?

static const int kMagic = 64; // (1)
constexpr int kMagic = 64;    // (2)

(1) travaille aussi pour C++98/03 compilateurs, au lieu (2) nécessite au moins C++11. Existe-il d'autres différences entre les deux? Si l'un ou l'autre être préféré moderne de code C++, et pourquoi?


MODIFIER

J'ai essayé cet exemple de code avec Godbolt du CE:

int main()
{
#define USE_STATIC_CONST
#ifdef USE_STATIC_CONST
  static const int kOk = 0;
  static const int kError = 1;
#else
  constexpr int kOk = 0;
  constexpr int kError = 1;
#endif
  return kOk;
}

et pour l' static const des cas c'est l'assembly généré par GCC 6.2:

main::kOk:
        .zero   4
main::kError:
        .long   1
main:
        push    rbp
        mov     rbp, rsp
        mov     eax, 0
        pop     rbp
        ret

D'autre part, pour constexpr il est:

main:
        push    rbp
        mov     rbp, rsp
        mov     DWORD PTR [rbp-4], 0
        mov     DWORD PTR [rbp-8], 1
        mov     eax, 0
        pop     rbp
        ret

Bien qu'à l' -O3 dans les deux cas, je reçois le même (optimisé) de l'assemblée:

main:
        xor     eax, eax
        ret

EDIT #2

J'ai essayé ce code simple (en direct sur Ideone):

#include <iostream>
using namespace std;

int main() {
    const int k1 = 10;
    constexpr int k2 = 2*k1;
    cout << k2 << '\n';
    return 0;
}

ce qui montre que const int k1 est évaluée au moment de la compilation, comme il est utilisé pour calculer le constexpr int k2.

Cependant, il semble y avoir différents comportements pour doubles. J'ai créé une autre question pour que ici.

53voto

Guillaume Racicot Points 1106

constexpr variable est la garantie d'avoir une valeur disponibles au moment de la compilation. alors qu' static const membres ou const variable peut signifier soit un moment de la compilation, de la valeur ou une valeur d'exécution. En tapant constexpr exprimez votre intention d'un moment de la compilation de la valeur de façon beaucoup plus explicite que const.

Une chose de plus, en C++17, constexpr donnée membre statique des variables vont être en ligne trop. Cela signifie que vous pouvez omettre le sort de la définition de l' static constexpr variables, mais pas static const.


Comme une demande dans la section des commentaires, voici une explication plus détaillée static const en fonction de la portée.

Un static const variable à portée de la fonction est à peu près la même, mais au lieu d'avoir un stockage automatique de la durée, il est statique de la durée de stockage. Que signifie, c'est en quelque sorte l'équivalent de déclarer la variable comme globale, mais uniquement accessible dans la fonction.

Il est vrai que l' static variable est initialiser lors du premier appel de la fonction, mais puisqu'il est const trop, le compilateur va essayer de l'inclure la valeur et d'optimiser la variable complètement. Ainsi, dans une fonction, si la valeur est connue au moment de la compilation pour cette variable, le compilateur le plus susceptible d'optimiser la.

Toutefois, si la valeur n'est pas connue au moment de la compilation pour un static const à portée de la fonction, il pourrait silencieusement faire de votre fonction (un petit peu) plus lent, car il a pour initialiser la valeur au moment de l'exécution de la première fois que la fonction est appelée. De Plus, il dispose de vérifier si la valeur est initialisée à chaque fois que la fonction est appelée.

C'est l'avantage d'un constexpr variable. Si la valeur n'est pas connue au moment de la compilation, c'est une erreur de compilation, pas un ralentissement de la fonction. Alors si vous n'avez aucun moyen de déterminer la valeur de la variable au moment de la compilation, alors le compilateur va tout vous raconter et vous pouvez faire quelque chose à ce sujet.

32voto

AndreyT Points 139512

Tant que nous parlons de déclarer des constantes de compilation de scalaire entier ou des types enum, il n'y a absolument aucune différence entre l'utilisation d' const (static const dans l'étendue de classe) ou constexpr.

Notez que les compilateurs sont nécessaires pour appuyer static const int objets (déclarée constante avec les initialiseurs) dans des expressions constantes, ce qui signifie qu'ils n'ont aucun choix mais pour traiter de tels objets comme des constantes de compilation. En outre, aussi longtemps que ces objets restent odr-utilisés, ils ne nécessitent pas de définition, ce qui démontre qu'ils ne sont pas être utilisés comme valeurs d'exécution.

Aussi, les règles de la constante d'initialisation de prévenir les locaux static const int objets d'être initialisés de façon dynamique, ce qui signifie qu'il n'y a pas de perte de performances pour déclarer de tels objets localement. En outre, l'immunité de l'intégrale static objets de la commande des problèmes d'initialisation statique est une caractéristique très importante de la langue.

constexpr est une extension et de la généralisation de la notion qui a été initialement mis en œuvre en C++ par const avec une constante de l'initialiseur. Pour les types integer constexpr n'offre pas grand chose de plus sur ce qu' const c'est déjà fait. constexpr simplement effectue un check de la "constness" de l'initialiseur. Cependant, on peut dire que l' constexpr est une fonction conçue spécialement à cet effet afin qu'il s'adapte mieux du point de vue stylistique.

Prograide.com

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.

Powered by:

X