C ++ Const Explication Explication

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

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

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

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

const int* const désigne un pointeur constant sur un int constant, c’est-à-dire un pointeur qui ne peut pas être changé, sur un int qui ne peut pas être modifié: la seule différence entre cela et const int& est qu’il peut être null

const int* const& signifie une référence à un pointeur constant sur un int constant. Les pointeurs ne sont généralement pas passés par référence. const int* & plus de sens car cela voudrait dire que le pointeur pourrait être changé pendant l’appel de la méthode, ce qui serait la seule raison pour laquelle je peux voir passer un pointeur par référence, const int* const& en tant que const int* const sauf qu’il est probablement moins efficace, car les pointeurs sont des types de données de base (POD) et ceux-ci devraient en général être transmis par valeur.

Il est plus facile à comprendre si vous réécrivez cela en tant que tout à fait é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; 

alors 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 à gauche est const (ne peut pas être modifié pour pointer vers une adresse différente).

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

# 2 dit que le pointeur à gauche est const .

# 1 dit que l’ int à gauche est const .

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

Tout d’abord, const T est équivalent à T const .

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

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

const int*const& devient int const*const& , donc c’est une référence à un pointeur const à un const int . Passer un pointeur const par des références n’a aucun sens non plus – vous ne pouvez pas modifier la valeur référencée puisque le pointeur est const et que les références et les pointeurs occupent un stockage égal.

La dernière const indique que la méthode ne modifie pas this object. Le pointeur this dans le corps de la méthode aura la déclaration (théorique) T const * const this . Cela signifie qu’un object const T* pourra appeler T::Method3() .

Un moyen facile de se souvenir des règles de const est d’y penser ainsi: const s’applique à la chose à sa gauche, sauf s’il n’y a rien à sa gauche.

Donc, dans le cas de const int * const , le premier const n’a rien à sa gauche, il s’applique donc à 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 avez const int const * . Puisque les deux const s’appliquent à int cette expression est redondante et donc invalide.

J’aime utiliser la méthode “clock” ou “spiral” où, à partir du nom de l’identifiant (dans ce cas, Method3 ), on lit de gauche à droite, de gauche à droite, etc. décoder les conventions de nommage. Donc const int* const Method3(const int* const&) const est une méthode de classe qui ne change aucun membre de classe (de certaines classes non nommées) et prend une référence constante à un pointeur qui pointe sur un int constant et retourne un pointeur constant sur un int constant.

J’espère que cela t’aides,

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. eg you cannot say `++pointer` */ &) const; /* this method does not modify the instance/object which implements the method */ 

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

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

  1. Une méthode const ne peut pas modifier les membres (sauf s’ils sont mutable expresse)
  2. Un pointeur de const ne peut pas être modifié pour pointer vers autre chose
  3. Un const int (ou tout autre type) ne peut pas être modifié

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

const # 2: La valeur du pointeur renvoyée par la fonction elle-même est const. Ceci est un const inutile (bien que grammatiquement 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 sur un const int.

const # 4: La valeur du pointeur transmise 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 (probablement une fonction membre) est const, ce qui signifie qu’il n’est pas permis (a) d’atsortingbuer de nouvelles valeurs à des membres de l’object dont elle fait partie ou (b) d’appeler une fonction membre non-const sur l’object ou l’un de ses membres.

Un moyen simple de mémoriser le const en C ++ est de voir du code dans une 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. Lorsque vous voyez quelque part "const&" , ne vous sentez pas confus, const décrit quelque chose avant lui. La réponse à ce problème est donc évidente maintenant.

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

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 également 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.

  • const à la fin de la méthode est le qualificatif signifiant que l’état de l’object ne va pas être modifié.

  • 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 modifier la valeur vers laquelle il pointe.

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

Quelques exemples pourraient être intéressants pour démontrer ce concept, plus il y a d’imho.

 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!