web-dev-qa-db-fra.com

Explication de l'utilisation des constantes C ++

const int* const Method3(const int* const&) const;

Quelqu'un peut-il expliquer l'utilisation de chacun des const?

92
RoR

Lisez ceci: https://isocpp.org/wiki/faq/const-correctness

Le dernier const signifie que la fonction Method3 ne modifie pas les membres non mutables de sa classe.

const int* const signifie un pointeur constant vers un int constant: c'est-à-dire un pointeur qui ne peut pas être changé, vers un int qui ne peut pas être changé: la seule différence entre ceci et const int& est qu'il peut être null

const int* const& signifie une référence à un pointeur constant vers une constante int. Habituellement, les pointeurs ne sont pas transmis par référence; const int* & a plus de sens car cela signifierait que le pointeur pourrait être changé pendant l'appel de méthode, ce qui serait la seule raison pour laquelle je peux voir passer un pointeur par référence, const int* const& est à toutes fins utiles identique à const int* const sauf qu'il est probablement moins efficace car les pointeurs sont de simples types de données anciennes (POD) et ceux-ci doivent, en général, être transmis par valeur.

73
briantyler

Il est plus facile à comprendre si vous réécrivez cela comme étant complètement équivalent

// v───v───v───v───v───v───v───v───v───v───v───v─┬┐
//                                               ││
//  v──#1    v─#2             v──#3    v─#4      #5
   int const * const Method3(int const * const&) const;

puis lisez-le de droite à gauche.

# 5 dit que la déclaration de fonction entière à gauche est const, ce qui implique qu'il s'agit nécessairement d'une fonction membre plutôt que d'une fonction libre.

# 4 indique que le pointeur vers la gauche est const (ne peut pas être modifié pour pointer vers une adresse différente).

# 3 indique que le int à gauche est const (ne peut pas être modifié pour avoir une valeur différente).

# 2 indique que le pointeur vers la gauche est const.

# 1 indique que le int à gauche est const.

En mettant tout cela ensemble, vous pouvez lire ceci comme une fonction membre const nommée Method3 qui prend une référence vers un pointeur const vers un int const (ou un const int, si vous préférez) et renvoie un pointeur const vers un int const (const int).

(N.b. # 2 est entièrement superfl .)

100
ildjarn

Tout d'abord, const T Équivaut à T const.

const int* const Est donc équivalent à int const * const.

Lorsque vous lisez des expressions contenant beaucoup de jetons et de pointeurs const, essayez toujours de lisez-les de droite à gauche (après avoir appliqué la transformation ci-dessus). Donc, dans ce cas, la valeur de retour est un pointeur const vers un const int. Faire le pointeur lui-même const n'a aucun sens ici car la valeur de retour n'est pas une valeur l qui pourrait être modifiée. Faire la pointee const, cependant, garantit que l'appelant ne peut pas modifier le int (ou tableau de ints) retourné par Method3.

const int*const& Devient int const*const&, C'est donc une référence à un pointeur const vers une const int . Passer un pointeur const par des références masculines n'a aucun sens non plus - vous ne pouvez pas modifier la valeur référencée car le pointeur est const et les références et les pointeurs occupent un espace de stockage égal, il n'y a donc pas non plus d'économie d'espace.

Le dernier const indique que la méthode ne modifie pas l'objet this. Le pointeur this dans le corps de la méthode aura la déclaration (théorique) T const * const this. Cela signifie qu'un objet const T* Pourra appeler T::Method3().

22

Un moyen facile de se souvenir des règles de const est de penser de cette façon: const s'applique à la chose à sa gauche, à moins qu'il n'y ait rien à sa gauche.

Donc, dans le cas de const int * const, le premier const n'a rien à sa gauche, donc il s'applique à int et le second a quelque chose à sa gauche, donc il s'applique au pointeur.

Cette règle vous indique également ce qui se passerait dans le cas où vous auriez const int const *. Puisque les deux const s'appliquent à int cette expression est redondante et donc invalide.

12
Yony

J'aime utiliser la méthode "horloge" ou "spirale" où à partir du nom de l'identifiant (dans ce cas Method3) Vous lisez dans les deux sens de gauche à droite -back-to-left, etc. afin de décoder les conventions de dénomination. Ainsi, const int* const Method3(const int* const&) const est une méthode de classe qui ne modifie aucun membre de classe (d'une classe sans nom) et prend une référence constante à un pointeur qui pointe vers une constante int et renvoie un pointeur constant vers une constante int.

J'espère que cela t'aides,

Jason

3
Jason
const /* don't modify the int or array of ints' value(s) */
int* const /* as a retval, ignored. useless declaration */
Method3(const /* don't modify the int or array of ints' value(s) */
int* const /* don't modify the pointer's value, the address to which `pointer` points to. e.g. you cannot say `++pointer` */
&) const; /* this method does not modify the instance/object which implements the method */
2
justin

Un moyen facile de se souvenir de la const en C++ est lorsque vous voyez du code sous forme comme:

XXX const;
const YYY;

XXX, YYY sera une composante constante,
XXX const forme:

function ( def var ) const;    ------#1
* const;                       ------#2

const YYY forme:

const int;                     ------#3
const double;

Les gens utilisent généralement ces types. Quand tu vois "const&" quelque part, ne vous sentez pas confus, const décrit quelque chose avant lui-même. donc la réponse à ce problème va de soi maintenant.

const int* const Method3(const int* const&) const;
  |          |             |          |       |
  #3         #2            #3         #2      #1
2
Albert Chen

La lecture de droite à gauche facilite la compréhension des modificateurs.

Une méthode const qui prend une référence à un pointeur const vers un const int appelé Method3 qui renvoie un pointeur const vers un const int.

  1. Une méthode const ne peut pas modifier les membres (à moins qu'ils ne soient explicitement mutable)
  2. Un pointeur const ne peut pas être changé pour pointer vers autre chose
  3. Un const int (ou tout autre type) ne peut pas être modifié
1
Nick Strupat

const # 1: Le pointeur renvoyé par Method3 fait référence à un const int.

const # 2: La valeur du pointeur retournée par la fonction elle-même est const. Il s'agit d'une constante inutile (bien que grammaticalement valide), car la valeur de retour d'une fonction ne peut pas être une valeur l.

const # 3: Le type de pointeur transmis par référence à la fonction pointe vers un const int.

const # 4: La valeur du pointeur passée par référence à la fonction est, elle-même, un pointeur const. Déclarer une valeur transmise à une fonction en tant que const serait normalement inutile, mais cette valeur est transmise par référence, elle peut donc être significative.

const # 5: La fonction (vraisemblablement une fonction membre) est const, ce qui signifie qu'il n'est pas autorisé à (a) attribuer de nouvelles valeurs aux membres de l'objet dont elle fait partie ou (b) appeler une fonction membre non const sur l'objet ou l'un de ses membres.

1
Jollymorphic

Je veux seulement mentionner que const int* const& est en effet une référence constante à const int*. Par exemple:

int i = 0;
int j = 1;
int* p = &i;
int* q = &j;
const int* const& cpref = p;
cpref = q; //Error: assignment of read-only reference 'cpref'

C'est aussi le cas pour int* const&, Ce qui signifie: "Une référence constante à int* ".
Mais const int*& est une référence non constante à const int*.
J'espère que cela t'aides.

1
MrDetective

Quelques exemples pourraient être sympas pour démontrer ce concept, plus c'est mieux à mon humble avis.

class TestClass
{
private:
   int iValue;
   int* oValuePtr;
   int& oValueRef;

public:
   int TestClass::ByValMethod1(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   int TestClass::ByValMethod2(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod3(int Value)
   {
      // Value can be modified
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod4(const int Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue can be modified
      iValue = Value;
      iValue += 1;

      // Return value can be modified
      return ++iValue;
   }

   const int TestClass::ByValMethod5(const int Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // iValue *cannot* be modified
      // Access through a const object
      iValue = Value;
      iValue += 1;

      // Return value *cannot* be modified
      // Access through a const object
      return ++iValue;
   }

   int& TestClass::ByRefMethod1(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int& TestClass::ByRefMethod2(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod3(int& Value)
   {
      // Value can be modified
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod4(const int& Value)
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   const int& TestClass::ByRefMethod5(const int& Value) const
   {
      // Value *cannot* be modified
      // Variable is const variable
      Value++;

      // oValueRef can be modified
      oValueRef = Value;
      oValueRef += 1;

      // Return value can be modified
      return ++oValueRef;
   }

   int* TestClass::PointerMethod1(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   int* TestClass::PointerMethod2(const int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr cannot be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod3(int* Value)
   {
      // Value can be modified
      Value++;

      // oValuePtr can be assigned
      oValuePtr = Value;

      // iValue can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod4(const int* Value)
   {
      // Value cannot be modified
      Value++;

      // oValuePtr *cannot* be assigned
      // const int* to int*
      oValuePtr = Value;

      // oValuePtr can be modified
      oValuePtr += 1;

      // Return value can be modified
      return ++oValuePtr;
   }

   const int* TestClass::PointerMethod5(const int* Value) const
   {
      // Value can be modified
      ++Value;

      // oValuePtr *cannot* be assigned
      // const int* to int* const
      // Access through a const object
      oValuePtr = Value;

      // oValuePtr *cannot* be modified
      // Access through a const object
      oValuePtr += 1;

      // Return value *cannot* be modified
      return ++oValuePtr;
   }
};

J'espère que ça aide!

0
Rastus7
  • const à la fin de la méthode est le qualificatif signifiant que l'état de l'objet ne va pas être changé.

  • const int*const& signifie recevoir par référence un pointeur const vers un emplacement const. Il ne peut ni changer pour pointer vers un emplacement différent ni changer la valeur vers laquelle il pointe.

  • const int*const est la valeur de retour qui est également un pointeur constant vers un emplacement constant.

0
Mahesh