Const avant ou const après?
Pour commencer, vous savez probablement que const
peut être utilisé pour présenter des données d'un objet ou d'un pointeur non modifiables ou les deux.
const Object* obj; //can't change data
Object* const obj; //can't change pointer
const Object* const obj; //can't change data or pointer
Cependant, vous pouvez également utiliser la syntaxe:
Object const *obj; //same as const Object* obj;
La seule chose qui semble compter, c'est de quel côté de l'astérisque, vous mettez le const
mot-clé. Personnellement, je préfère les mettre const
sur la gauche de la type pour spécifier des données n'est pas modifiable car je trouve qu'il se lit mieux, à mon de gauche à droite mentalité, mais dont la syntaxe est venu en premier?
Plus important encore, pourquoi il y a deux façons correctes de la spécification const
de données et dans quelle situation vous préférez ou besoin de l'un sur l'autre si?
Edit:
De sorte qu'il semble que cela a été une décision arbitraire, lorsque la norme pour la façon dont les compilateurs doivent interpréter les choses a été rédigé avant ma naissance. Depuis const
est appliqué à ce qui est à gauche du mot-clé (par défaut?) Je suppose qu'ils ont compris, il n'y a pas de mal à ajouter "raccourcis" pour appliquer des mots-clés et le type de qualificatifs à d'autres égards, au moins jusqu'à ce que les modifications de déclaration par l'analyse d'un * ou & ...
Ce fut le cas en C et puis je suppose?
- Dans les macros toujours ajouter
const
après le type, par exemple#define MAKE_CONST(T) T const
au lieu de#define MAKE_CONST(T) const T
de sorte queMAKE_CONST(int *)
correctement s'étendre àint * const
au lieu deconst int *
. - J'ai vu ces deux styles dénommé "est const" et "ouest " const".
- mais vraiment, il devrait être "est const" et "const ouest".
Vous devez vous connecter pour publier un commentaire.
Essentiellement, le motif de la position de
const
dans les spécificateurs avant qu'un astérisque n'a pas d'importance, c'est que le C de la grammaire a été défini ainsi par Kernighan et Ritchie.La raison, ils ont défini la grammaire de cette manière était probable que leur compilateur C analysé l'entrée de gauche à droite et a terminé le traitement de chaque jeton comme elle a consommé que. La consommation de la
*
jeton de changements de l'état actuel de la déclaration d'un type pointeur. Rencontreconst
après*
signifie laconst
qualificatif est appliqué à une déclaration de pointeur; en rencontrant avant le*
signifie le qualificatif est appliquée aux données souligné.Parce que la sémantique ne change pas si le
const
qualificatif avant ou après les spécificateurs de type, il est admis à l'autre.Une sorte semblable de cas se pose lors de la déclaration des pointeurs de fonction, d'où:
void * function1(void)
déclare une fonction qui retournevoid *
,void (* function2)(void)
déclare un pointeur de fonction à une fonction qui retournevoid
.De nouveau la chose à remarquer est que la syntaxe de la langue prend en charge une gauche à droite de l'analyseur.
*
analyseur de compilateur ne sait pas qu'il est pointeur donc il est const pour les données de la valeur. Après * elle est liée à la constante pointeur. Brillant. Et enfin, il explique pourquoi je peux faireconst char
ainsi quechar const
.const
de toujours venir après que la chose qualification... exactement, donc je peux toujours terminer le traitement de la const immédiatement après, je le consomme. Si cela semble être un argument pour interdisant ouest-const, plutôt que de permettre qu'il.++
opérateur? "La phrase", à mon humble avis, m'a aidé à comprendre il n'y avait aucune raison particulière autre que parce qu'ils le pouvaient. Peut-être qu'ils feraient un choix différent aujourd'hui, peut-être pas.const
sans vérifier si il est venu avant ou après.La règle est la suivante:
Je préfère utiliser const sur le droit de la chose à const juste parce que c'est "l'original" façon const est défini.
Mais je pense que c'est très subjectif point de vue.
Object const *
est un pointeur vers un const Objet. Si vous mettez laconst
sur la gauche, il se lise comme un pointeur vers un Objet qui est const, qui n'a pas vraiment de flux très bien.const
n'est pas un espace de stockage de classe, mais les gens ne sont pas des analyseurs).int *const p;
laconst
s'applique à la*
plutôt que la chose sur sa droite,p
, qui est bien sûr ce qui est const qualifiés dans ce cas.Je préfère la deuxième syntaxe. Il m'aide à garder une trace de ce qui est constant, par la lecture de la déclaration de type de droite à gauche:
Object const* const
, pasconst const Object*
. "const" ne peut pas être sur la gauche, sauf dans le cas spécial où tant de gens l'adore. (Voir Heath ci-dessus).L'ordre des mots dans une déclaration n'est pas fixe. Il existe de nombreuses solutions de rechange "le seul vrai ordre". Comme ce
ou devrait-il être
??
decl-specifier-seq
est une séquence dedecl-specifier
s. Il n'y a pas d'ordre donné par la grammaire, et le nombre d'événements pour chaque mot-clé est limitée uniquement par des règles sémantiques (vous pouvez avoir unconst
mais deuxlong
🙂unsigned
? J'ai penséunsigned long
etc. étaient des types qui leur est propre, et queunsigned
n'était pas vraiment un spécificateur de son propre chef?unsigned
est un type, le même queunsigned int
etint unsigned
.unsigned long
est un autre type, le même queunsigned long int
etint long unsigned
. Voir le modèle?;)
. OK, mercistatic
pour le pêle-mêle de mots, mais c'est seulement récemment que les compilateurs se sont plaints questatic
doit venir d'abord.unsigned
par lui-même est juste un raccourci pourunsigned int
(si ce n'était pas clair), de la même façonshort
par lui-même est le même queshort int
. (Bien faire attention, il y a une différence entre l'utilisation dechar
vsunsigned/signed char
... ce n'est pas un type de son propre, mais il a son propre sens, car unchar
pourrait être signé ou non signé à l'interne et il n'a pas vraiment d'importance qui, mais, fondamentalement, essayez de garder les choses cohérentes et pour les fonctions de bibliothèque standard, il suffit d'utiliser le plainechar
et de la laisser utiliser sa propre représentation interne.)La première règle consiste à utiliser quel que soit le format de votre région normes de codage
nécessite. D'après: mettre le
const
devant entraîne pas la fin dela confusion quand les typedefs sont impliqués, par exemple:
Si votre norme de codage permet de définition de type de pointeurs, puis il vraiment
devrait insister sur la mise const après le type. Dans tous les cas, mais
lorsqu'il est appliqué à la type, const doit suivre ce qu'il s'applique, de sorte
la cohérence plaide également en faveur de la const après. Mais de codage local
lignes directrices préséance sur tous les de ces, la différence n'est normalement pas important
assez pour revenir en arrière et modifier tout le code existant.
const std::string::const_iterator
ainsi, pour faire bonne mesure 😉const IntPtr p1
peut-être dire autre que "constante pointeur entier" (c'est à dire, "pointeur constant integer")? Personne dans leur bon esprit, même sans savoir commentIntPtr
est défini, pourrait penser quep1
est mutable. Et d'ailleurs, pourquoi serait-on penser, à tort, que*p1
est immuable? Qui plus est, en mettant l'const n'importe où ailleurs (par exemple,IntPtr const p1
), ne change pas la sémantique à tous.std::vector<T>::const_iterator
, où il n'est pas l'itérateur qui est const, mais ce qu'il désigne).const IntPtr p1
signifie la même chose queconst int *p1
(akaint const *p1
). Je n'aurais pas connu avec certitude ce que cela signifie et je voudrais vraiment avoir été confondu.Il y a des raisons historiques qui soit de gauche ou de droite est acceptable. Stroustrup a ajouté const en C++ en 1983, mais il n'a pas de C jusqu'à ce que C89/C90.
En C++ il y a une bonne raison de toujours utiliser const sur la droite. Vous allez être uniforme partout, parce que const fonctions de membre doit être déclaré ainsi:
const int& getInt();
int& const getInt();
int const& getInt();
est mieux que l'équivalentconst int& getInt();
alors queint& const getInt();
que vous la comparez avec est redondant (les références sont déjà const) si la régularité et l'habitude de donner un avertissement. De toute façon, const sur une fonction membre des changements de lathis
pointeur dans la fonction deFoo* const
àFoo const* const
.const
sur une fonction membre ne signifie pas du tout la même chose—ou estvoid set(int)&;
quelque sorte d'une référence à une fonction?