Exam-Lib: 6.11 - Variables de référence C++ | Exam-Lib
  1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.
Dismiss Notice
Welcome to our Education website, plz like our page facebook to support us. Thank You and wish you good navigation

6.11 - Variables de référence C++

abdelouafiNov 25, 2018

    1. abdelouafi

      abdelouafi Administrator Staff Member

      Messages:
      725
      Likes Received:
      14
      Trophy Points:
      38
      Joined
      Sep 13, 2016
      Jusqu'à présent, nous avons discuté de deux types de variables de base:

      • Les variables normales, qui contiennent des valeurs directement.
      • Les pointeurs, qui contiennent l'adresse d'une autre valeur (ou null) et peuvent être déréférencés pour récupérer la valeur à l'adresse indiquée.

      Les références sont le troisième type de base de variable pris en charge par C ++. Une référence est un type de variable C ++ qui agit comme un alias vers un autre objet ou une autre valeur.

      C ++ prend en charge trois types de références:

      Références à des valeurs non constantes (généralement appelées simplement "références" ou "références non constantes"), dont nous parlerons dans cette leçon.
      Références aux valeurs const (souvent appelées «références const»), dont nous parlerons dans la leçon suivante.
      C ++ 11 a ajouté des références de valeur r, que nous couvrirons en détail dans le chapitre sur la sémantique des déplacements.
      Références à des valeurs non constantes

      Une référence (à une valeur non-const) est déclarée en utilisant une esperluette (&) entre le type de référence et le nom de la variable:
      Code:
      int value = 5; // normal integer
      int &ref = value; // reference to variable value
      Dans ce contexte, l'esperluette ne signifie pas “adresse de”, mais “référence à”.

      Les références aux valeurs non constantes sont souvent simplement appelées «références».

      Les références comme alias

      Les références agissent généralement de manière identique aux valeurs qu’elles référencent. En ce sens, une référence agit comme un alias pour l'objet référencé. Par exemple:
      Code:
      int x = 5; // normal integer
      int &y = x; // y is a reference to x
      int &z = y; // z is also a reference to x
      Dans l'extrait de code ci-dessus, définir ou obtenir la valeur de x, y ou z fera la même chose (définir ou obtenir la valeur de x).

      Jetons un coup d’œil aux références utilisées:
      Code:
      #include <iostream>
      int main()
      {
          int value = 5; // normal integer
          int &ref = value; // reference to variable value
          value = 6; // value is now 6
          ref = 7; // value is now 7
          std::cout << value; // prints 7
          ++ref;
          std::cout << value; // prints 8
          return 0;
      }
      Ce code imprime:
      7
      8


      Dans l'exemple ci-dessus, ref et value sont traités comme des synonymes.

      L'utilisation de l'opérateur address-of sur une référence renvoie l'adresse de la valeur référencée:
      Code:
      cout << &value; // prints 0012FF7C
      cout << &ref; // prints 0012FF7C
      Tout comme vous vous en doutez, si ref agit comme un alias pour la valeur.

      Un bref aperçu des valeurs l et des valeurs r

      Retour dans la leçon 1.3 - Pour un premier regard sur les variables, l’initialisation et l’affectation, nous avons parlé des valeurs l et des valeurs r et vous avons dit de ne pas trop vous inquiéter. Nous arrivons enfin au point où il devient utile de réutiliser ces termes.

      Pour rappel, la L-valeurs sont des objets qui ont une adresse de mémoire définie (comme les variables), et persistent au-delà d'une seule expression. Les valeurs r sont des valeurs temporaires qui n'ont pas d'adresse de mémoire définie et qui ont uniquement une étendue d'expression. Les valeurs R incluent à la fois les résultats d'expressions (par exemple 2 + 3) et les littéraux.

      Les références doivent être initialisées

      Les références doivent être initialisées à la création:
      Code:
      int value = 5;
      int &ref = value; // valid reference, initialized to variable value
      int &invalidRef; // invalid, needs to reference something
      Contrairement aux pointeurs, qui peuvent contenir une valeur null, une référence nulle n'existe pas.

      Les références à des valeurs non constantes ne peuvent être initialisées qu'avec des valeurs non constantes. Ils ne peuvent pas être initialisés avec des valeurs const l ou r.
      Code:
      int x = 5;
      int &ref1 = x; // okay, x is an non-const l-value
      const int y = 7;
      int &ref2 = y; // not okay, y is a const l-value
      int &ref3 = 6; // not okay, 6 is an r-value
      Notez qu'au milieu, vous ne pouvez pas initialiser une référence non-const avec un objet const. Sinon, vous pourrez modifier la valeur de l'objet const via la référence, ce qui violerait la const-ness du objet.

      Les références ne peuvent pas être réaffectées

      Une fois initialisée, une référence ne peut pas être modifiée pour référencer une autre variable. Considérez l'extrait suivant:
      Code:
      int value1 = 5;
      int value2 = 6;
      int &ref = value1; // okay, ref is now an alias for value1
      ref = value2; // assigns 6 (the value of value2) to value1 -- does NOT change the reference!
      Notez que la deuxième déclaration peut ne pas faire ce que vous pourriez attendre! Au lieu de réaffecter ref à la variable de référence valeur2, elle affecte plutôt la valeur de valeur2 à valeur1 (dont ref est une référence).

      Les références en tant que paramètres de fonction

      Les références sont le plus souvent utilisées comme paramètres de fonction. Dans ce contexte, le paramètre de référence agit comme un alias pour l'argument et aucune copie de l'argument n'est créée dans le paramètre. Cela peut conduire à de meilleures performances si l'argument est volumineux ou coûteux à copier.

      Dans la leçon 6.8 - Pointeurs et tableaux, nous avons expliqué comment le fait de passer un argument de pointeur à une fonction permet à la fonction de déréférencer le pointeur pour modifier directement la valeur de l'argument.

      Les références fonctionnent de la même manière à cet égard. Comme le paramètre reference agit comme un alias pour l'argument, une fonction utilisant un paramètre reference peut modifier l'argument transmis:
      Code:
      #include <iostream>
      // ref is a reference to the argument passed in, not a copy
      void changeN(int &ref)
      {
          ref = 6;
      }
      int main()
      {
          int n = 5;
          std::cout << n << '\n';
          changeN(n); // note that this argument does not need to be a reference
          std::cout << n << '\n';
          return 0;
      }
      Ce programme imprime:
      5
      6

      Lorsque l'argument n est transmis à la fonction, le paramètre de fonction ref est défini comme référence à l'argument n. Cela permet à la fonction de changer la valeur de n via ref! Notez que n n'a pas besoin d'être une référence elle-même.

      Meilleure pratique: Passer des arguments par référence non-const lorsque l'argument doit être modifié par la fonction.

      Le principal inconvénient de l'utilisation de références non const en tant que paramètres de fonction est que l'argument doit être une valeur l non const. Cela peut être restrictif. Nous parlerons davantage de cela (et de la façon de le contourner) dans la prochaine leçon.

      Utilisation de références pour passer des tableaux de style C à des fonctions

      L'un des problèmes les plus gênants avec les tableaux de style C est que, dans la plupart des cas, ils se décomposent en indicateurs lorsqu'ils sont évalués. Cependant, si un tableau de style C est passé par référence, cette décroissance ne se produit pas.

      Voici un exemple (h / t au lecteur nascardriver):
      Code:
      #include <iostream>
      // Note: You need to specify the array size in the function declaration
      void printElements(int (&arr)[4])
      {
        int length{ sizeof(arr) / sizeof(arr[0]) }; // we can now do this since the array won't decay
       
        for (int i{ 0 }; i < length; ++i)
        {
          std::cout << arr[i] << std::endl;
        }
      }
      int main()
      {
          int arr[]{ 99, 20, 14, 80 };
         
          printElements(arr);
          return 0;
      }
      Notez que pour que cela fonctionne, vous devez explicitement définir la taille du tableau dans le paramètre.

      Les références comme raccourcis

      Une utilisation secondaire (beaucoup moins utilisée) des références est de fournir un accès plus facile aux données imbriquées. Considérons la structure suivante:
      Code:
      struct Something
      {
          int value1;
          float value2;
      };
      struct Other
      {
          Something something;
          int otherValue;
      };
      Other other;
      Disons que nous devions travailler avec le champ value1 de la structure Something d’autre. Normalement, nous accédons à ce membre en tant qu'autre.quelque chose.value1. S'il existe plusieurs accès distincts à ce membre, le code peut devenir compliqué. Les références vous permettent d'accéder plus facilement au membre:
      Code:
      int &ref = other.something.value1;
      // ref can now be used in place of other.something.value1
      Les deux déclarations suivantes sont donc identiques:
      Code:
      other.something.value1 = 5;
      ref = 5;
      Cela peut aider à garder votre code plus propre et plus lisible.

      Références vs pointeurs

      Les références et les pointeurs ont une relation intéressante - une référence se comporte comme un pointeur implicitement déréférencé lors de l'accès (les références sont généralement implémentées en interne par le compilateur à l'aide de pointeurs). Ainsi, compte tenu de ce qui suit:
      Code:
      int value = 5;
      int *const ptr = &value;
      int &ref = value;
      * ptr et ref évaluer à l'identique. Par conséquent, les deux déclarations suivantes produisent le même effet:
      Code:
      *ptr = 5;
      ref = 5;
      Comme les références doivent être initialisées avec des objets valides (ne peuvent pas être null) et ne peuvent pas être modifiées une fois définies, les références sont généralement beaucoup plus sûres à utiliser que les pointeurs (car il n’ya aucun risque de déréférencer un pointeur nul). Cependant, leurs fonctionnalités sont également un peu plus limitées.

      Si une tâche donnée peut être résolue avec une référence ou un pointeur, la référence doit généralement être préférée. Les pointeurs ne doivent être utilisés que dans des situations où les références ne sont pas suffisantes (comme l’allocation dynamique de mémoire).

      Résumé

      Les références nous permettent de définir des alias pour d'autres objets ou valeurs. Les références à des valeurs non constantes ne peuvent être initialisées qu'avec des valeurs non constantes. Les références ne peuvent pas être réaffectées une fois initialisées.

      Les références sont le plus souvent utilisées en tant que paramètres de fonction lorsque nous voulons modifier la valeur de l'argument ou lorsque nous voulons éviter de faire une copie coûteuse de l'argument.
       
      Loading...

      Merci de partager ce post sur facebook

    2. Merci d'aimer notre facebook page

Share This Page