La réponse courte est que non seulement elle est static
utile, mais elle sera toujours souhaitée.
Tout d'abord, notez que static
et constexpr
sont complètement indépendants les uns des autres. static
définit la durée de vie de l'objet pendant l'exécution; constexpr
spécifie que l'objet doit être disponible lors de la compilation. La compilation et l'exécution sont disjointes et non contiguës, à la fois dans le temps et dans l'espace. Donc, une fois le programme compilé, ce constexpr
n'est plus pertinent.
Chaque variable déclarée constexpr
est implicitement const
mais const
et static
est presque orthogonale (sauf pour l'interaction avec les static const
entiers.)
Le C++
modèle objet (§1.9) exige que tous les objets autres que les champs de bits occupent au moins un octet de mémoire et aient des adresses; en outre, tous ces objets observables dans un programme à un moment donné doivent avoir des adresses distinctes (paragraphe 6). Cela n'oblige pas tout à fait le compilateur à créer un nouveau tableau sur la pile pour chaque invocation d'une fonction avec un tableau const non statique local, car le compilateur pourrait se réfugier dans le as-if
principe à condition qu'il puisse prouver qu'aucun autre objet de ce type ne peut être observé.
Cela ne sera malheureusement pas facile à prouver, à moins que la fonction ne soit triviale (par exemple, elle n'appelle aucune autre fonction dont le corps n'est pas visible dans l'unité de traduction) car les tableaux, plus ou moins par définition, sont des adresses. Ainsi, dans la plupart des cas, le const(expr)
tableau non statique devra être recréé sur la pile à chaque invocation, ce qui va à l'encontre du point de pouvoir le calculer au moment de la compilation.
D'un autre côté, un static const
objet local est partagé par tous les observateurs et peut en outre être initialisé même si la fonction dans laquelle il est défini n'est jamais appelée. Donc rien de ce qui précède ne s'applique, et un compilateur est libre non seulement de n'en générer qu'une seule instance; il est libre d'en générer une seule instance dans un stockage en lecture seule.
Vous devriez donc certainement utiliser static constexpr
dans votre exemple.
Cependant, il y a un cas où vous ne voudriez pas utiliser static constexpr
. À moins qu'un constexpr
objet déclaré ne soit utilisé ou déclaré par ODRstatic
, le compilateur est libre de ne pas l'inclure du tout. C'est assez utile, car cela permet d'utiliser des constexpr
tableaux temporaires au moment de la compilation sans polluer le programme compilé avec des octets inutiles. Dans ce cas, vous ne voudriez clairement pas utiliser static
, car il static
est susceptible de forcer l'objet à exister au moment de l'exécution.
const
unconst
objet, uniquement à partir deconst X*
qui pointe vers unX
. Mais ce n'est pas le but; le fait est que les objets automatiques ne peuvent pas avoir d'adresses statiques. Comme je l'ai dit,constexpr
cesse d'avoir un sens une fois la compilation terminée, il n'y a donc rien à jeter (et peut-être rien du tout, car il n'est même pas garanti que l'objet existe au moment de l'exécution.)static
etconstexpr
mais expliquez qu'ils sont orthogonaux et indépendants, faisant des choses différentes. Vous mentionnez ensuite une raison pour ne PAS combiner les deux car cela ignorerait l'utilisation de l'ODR (ce qui semble utile). Oh et je ne vois toujours pas pourquoi static devrait être utilisé avec constexpr puisque static est pour les choses d'exécution. Vous n'avez jamais expliqué pourquoi statique avec constexpr est important.static constexpr
(cela empêche le tableau constant de devoir être recréé à chaque appel de fonction), mais j'ai modifié quelques mots qui pourraient le rendre plus clair. Merci.constexpr
variable constante n'est utilisée que dans des contextes de compilation et n'est jamais nécessaire au moment de l'exécution,static
cela n'a aucun sens, car au moment où vous arrivez à l'exécution, la valeur a été effectivement "intégrée". Cependant, siconstexpr
est utilisé dans des contextes d'exécution (en d'autres termes, leconstexpr
devrait être converti enconst
implicitement, et disponible avec une adresse physique pour le code d'exécution), il voudrastatic
assurer la conformité ODR, etc. C'est ce que je comprends, au moins.static constexpr int foo = 100;
. Il n'y a aucune raison pour que le compilateur ne puisse pas substituer l'usage defoo
partout pour littéral100
, à moins que le code ne fasse quelque chose comme&foo
. Doncstatic
onfoo
n'a aucune utilité dans ce cas puisqu'ilfoo
n'existe pas à l'exécution. Encore une fois, tout dépend du compilateur.En plus de la réponse donnée, il convient de noter que le compilateur n'est pas obligé d'initialiser la
constexpr
variable au moment de la compilation, sachant que la différence entreconstexpr
etstatic constexpr
est que pour l'utiliser,static constexpr
vous vous assurez que la variable n'est initialisée qu'une seule fois.Le code suivant montre comment la
constexpr
variable est initialisée plusieurs fois (avec la même valeur cependant), alors qu'ellestatic constexpr
n'est sûrement initialisée qu'une seule fois.De plus, le code compare l'avantage de
constexpr
contreconst
en combinaison avecstatic
.Sortie de programme possible:
Comme vous pouvez le voir, vous êtes
constexpr
initialisé plusieurs fois (l'adresse n'est pas la même) tandis que lestatic
mot clé garantit que l'initialisation n'est effectuée qu'une seule fois.la source
constexpr const short constexpr_short
pour donner une erreur si constexpr_short est à nouveau initialiséconstexpr const
n'a aucun sens carconstexpr
déjàconst
, l'ajoutconst
une ou plusieurs fois est ignoré par le compilateur. Vous essayez d'attraper une erreur mais ce n'est pas une erreur, c'est ainsi que fonctionnent la plupart des compilateurs.