clockwise - int* c++




Quelle est la différence entre const int*, const int*const et int const*? (9)

Je gâche toujours comment utiliser const int* , const int * const et int const * correctement. Existe-t-il un ensemble de règles définissant ce que vous pouvez et ne pouvez pas faire?

Je veux connaître toutes les choses à faire et à ne pas faire en termes d'affectations, de passage aux fonctions, etc.


  1. Référence constante:

    Une référence à une variable (ici int), qui est constante. Nous passons la variable comme référence principalement, parce que les références sont de taille plus petite que la valeur réelle, mais il y a un effet secondaire et c'est parce que c'est comme un alias à la variable réelle. Nous pouvons accidentellement changer la variable principale grâce à notre accès complet à l'alias, donc nous le rendons constant pour éviter cet effet secondaire.

    int var0 = 0;
    const int &ptr1 = var0;
    ptr1 = 8; // Error
    var0 = 6; // OK
    
  2. Les pointeurs constants

    Une fois qu'un pointeur constant pointe vers une variable, il ne peut pointer vers aucune autre variable.

    int var1 = 1;
    int var2 = 0;
    
    int *const ptr2 = &var1;
    ptr2 = &var2; // Error
    
  3. Pointeur à constante

    Un pointeur à travers lequel on ne peut pas changer la valeur d'une variable pointée est connu sous le nom de pointeur vers la constante.

    int const * ptr3 = &var2;
    *ptr3 = 4; // Error
    
  4. Pointeur constant vers une constante

    Un pointeur constant vers une constante est un pointeur qui ne peut ni changer l'adresse vers laquelle elle pointe, ni changer la valeur conservée à cette adresse.

    int var3 = 0;
    int var4 = 0;
    const int * const ptr4 = &var3;
    *ptr4 = 1;     // Error
     ptr4 = &var4; // Error
    

C'est simple mais difficile. Veuillez noter que nous pouvons échanger le qualificatif const avec n'importe quel type de données ( int , char , float , etc.).

Voyons voir les exemples ci-dessous.

const int *p ==> *p est en lecture seule [ p est un pointeur vers un entier constant]

int const *p ==> *p est en lecture seule [ p est un pointeur vers un entier constant]

int *p const ==> Déclaration incorrecte . Le compilateur génère une erreur de syntaxe.

int *const p ==> p est en lecture seule [ p est un pointeur constant vers un entier]. Comme le pointeur p est ici en lecture seule, la déclaration et la définition doivent être au même endroit.

const int *p const ==> Déclaration incorrecte . Le compilateur génère une erreur de syntaxe.

const int const *p ==> *p est en lecture seule

const int *const p1 ==> *p et p sont en lecture seule [ p est un pointeur constant vers un entier constant]. Comme le pointeur p est ici en lecture seule, la déclaration et la définition doivent être au même endroit.

int const *p const ==> Déclaration incorrecte . Le compilateur génère une erreur de syntaxe.

int const int *p ==> Déclaration incorrecte . Le compilateur génère une erreur de syntaxe.

int const const *p ==> *p est en lecture seule et équivaut à int const *p

int const *const p ==> *p et p sont en lecture seule [ p est un pointeur constant vers un entier constant]. Comme le pointeur p est ici en lecture seule, la déclaration et la définition doivent être au même endroit.


Cette question montre précisément pourquoi j'aime faire les choses comme je l'ai mentionné dans ma question est const après type id acceptable?

En bref, je trouve que la façon la plus simple de se souvenir de la règle est que le "const" va après la chose à laquelle il s'applique. Donc dans votre question, "int const *" signifie que int est constant, alors que "int * const" signifierait que le pointeur est constant.

Si quelqu'un décide de le mettre à l'avant même (par exemple: "const int *"), comme une exception spéciale dans ce cas, il s'applique à la chose après.

Beaucoup de gens aiment utiliser cette exception spéciale parce qu'ils pensent que c'est plus joli. Je ne l'aime pas, parce que c'est une exception, et donc confond les choses.


Comme à peu près tout le monde a souligné:

Quelle est la différence entre const X* p , X* const p et const X* const p ?

Vous devez lire les déclarations de pointeur de droite à gauche.

  • const X* p signifie "p pointe sur un X qui est const": l'objet X ne peut pas être changé via p.

  • X* const p signifie que "p est un pointeur const vers un X qui n'est pas const": vous ne pouvez pas changer le pointeur p lui-même, mais vous pouvez changer l'objet X via p.

  • const X* const p signifie que "p est un pointeur const sur un X qui est const": vous ne pouvez pas changer le pointeur p lui-même, ni changer l'objet X via p.


J'avais le même doute que toi jusqu'à ce que je tombe sur ce book du gourou C ++ Scott Meyers. Reportez-vous au troisième élément de ce livre où il parle en détail de l'utilisation de const .

Suivez simplement ce conseil

  1. Si le mot const apparaît à gauche de l'astérisque, ce qui est indiqué est constant
  2. Si le mot const apparaît à droite de l'astérisque, le pointeur lui-même est constant
  3. Si const apparaît des deux côtés, les deux sont constants

Je pense que tout est déjà répondu ici, mais je veux juste ajouter que vous devriez vous méfier des typedef s! Ils ne sont pas seulement des remplacements de texte.

Par exemple:

typedef char *ASTRING;
const ASTRING astring;

Le type d' astring est char * const , pas const char * . C'est une raison pour laquelle j'ai toujours tendance à mettre const à la droite du type, et jamais au début.


La syntaxe de déclaration C et C ++ a été décrite à plusieurs reprises comme une expérience ratée par les concepteurs originaux.

Au lieu de cela, nommons le type "pointeur vers Type "; Je l'appellerai Ptr_ :

template< class Type >
using Ptr_ = Type*;

Maintenant, Ptr_<char> est un pointeur vers char .

Ptr_<const char> est un pointeur vers const char .

Et const Ptr_<const char> est un pointeur const char vers const char .

Là.


Lisez-le à l'envers (comme conduit par Clockwise / Spiral Rule ):

  • int* - pointeur vers int
  • int const * - pointeur vers const int
  • int * const - const pointeur vers int
  • int const * const - const pointeur vers const int

Maintenant, le premier const peut être de chaque côté du type:

  • const int * == int const *
  • const int * const == int const * const

Si vous voulez vraiment devenir fou, vous pouvez faire des choses comme ça:

  • int ** - pointeur vers le pointeur vers int
  • int ** const - un pointeur const vers un pointeur vers un int
  • int * const * - un pointeur vers un pointeur const vers un int
  • int const ** - un pointeur vers un pointeur vers un int int
  • int * const * const - un pointeur const vers un pointeur const vers un int
  • ...

Et pour s'assurer que nous sommes clair sur la signification de const

const int* foo;
int *const bar; //note, you actually need to set the pointer 
                //here because you can't change it later ;)

foo est un pointeur variable vers un entier constant. Cela vous permet de changer ce que vous pointez mais pas la valeur que vous pointez. Le plus souvent, cela est vu avec des chaînes de style C où vous avez un pointeur vers un const char . Vous pouvez changer la chaîne que vous pointez mais vous ne pouvez pas changer le contenu de ces chaînes. Ceci est important lorsque la chaîne se trouve dans le segment de données d'un programme et ne doit pas être modifiée.

bar est un pointeur fixe ou fixe vers une valeur qui peut être modifiée. C'est comme une référence sans le sucre syntaxique supplémentaire. De ce fait, vous utiliseriez généralement une référence dans laquelle vous utiliseriez un pointeur T* const moins que vous n'ayez besoin de pointeurs NULL .


Utilisation simple de 'const'

L'utilisation la plus simple consiste à déclarer une constante nommée. Pour ce faire, on déclare une constante comme si c'était une variable mais on ajoute 'const' avant elle. On doit l'initialiser immédiatement dans le constructeur car, bien sûr, on ne peut pas définir la valeur plus tard car cela la modifierait. Par exemple,

const int Constant1=96; 

va créer une constante entière, dénuée d'imagination 'Constant1', avec la valeur 96.

Ces constantes sont utiles pour les paramètres qui sont utilisés dans le programme mais n'ont pas besoin d'être modifiés après la compilation du programme. Il a un avantage pour les programmeurs sur la commande '#define' du préprocesseur C en ce qu'il est compris et utilisé par le compilateur lui-même, non seulement substitué dans le programme par le préprocesseur avant d'atteindre le compilateur principal, donc les messages d'erreur sont beaucoup plus utiles .

Il fonctionne également avec des pointeurs, mais il faut faire attention où 'const' pour déterminer si le pointeur ou ce qu'il pointe est constant ou les deux. Par exemple,

const int * Constant2 

déclare que Constant2 est un pointeur variable vers un entier constant et

int const * Constant2

est une syntaxe alternative qui fait la même chose, alors que

int * const Constant3

déclare que Constant3 est pointeur constant vers un entier variable et

int const * const Constant4

déclare que Constant4 est un pointeur constant vers un entier constant. Fondamentalement, 'const' s'applique à tout ce qui est sur sa gauche immédiate (autre que s'il n'y a rien, auquel cas il s'applique à ce qui est son droit immédiat).

ref: http://duramecho.com/ComputerInformation/WhyHowCppConst.html





const