Exam-Lib: 6.15 - Une introduction à std :: array 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.15 - Une introduction à std :: array C++

abdelouafiDec 10, 2018

    1. abdelouafi

      abdelouafi Administrator Staff Member

      Messages:
      725
      Likes Received:
      14
      Trophy Points:
      38
      Joined
      Sep 13, 2016
      Dans les leçons précédentes, nous avons beaucoup parlé de tableaux fixes et dynamiques. Bien que les deux soient construits directement dans le langage C ++, ils présentent tous deux des inconvénients: les tableaux fixes se décomposent en pointeurs, perdent l'information de longueur de tableau, et les tableaux dynamiques posent des problèmes de désallocation et sont difficiles à redimensionner sans erreur.

      Pour résoudre ces problèmes, la bibliothèque standard C ++ inclut des fonctionnalités facilitant la gestion des tableaux, std :: array et std :: vector. Nous allons examiner std :: array dans cette leçon et std :: vector dans la suivante.

      Une introduction à std :: array en C ++ 11

      Introduit dans C ++ 11, std :: array fournit des fonctionnalités de tableau fixes qui ne s’affaiblissent pas lorsqu’elles sont transmises à une fonction. std :: array est défini dans l'en-tête du tableau, à l'intérieur de l'espace de noms std.

      Déclarer une variable std :: array est simple:
      Code:
      #include <array>
      std::array<int, 3> myArray; // declare an integer array with length 3
      Tout comme l'implémentation native des tableaux fixes, la longueur d'un std :: array doit être définie au moment de la compilation.

      std :: array peut être initialisé en utilisant une liste d'initialisation ou une initialisation uniforme:
      Code:
      std::array<int, 5> myArray = { 9, 7, 5, 3, 1 }; // initialization list
      std::array<int, 5> myArray2 { 9, 7, 5, 3, 1 }; // uniform initialization
      Contrairement aux tableaux fixes intégrés, avec std :: array, vous ne pouvez pas omettre la longueur du tableau lorsque vous fournissez un initialiseur:
      Code:
      std::array<int, > myArray = { 9, 7, 5, 3, 1 }; // illegal, array length must be provided
      
      Vous pouvez également affecter des valeurs au tableau à l'aide d'une liste d'initialisation.
      Code:
      std::array<int, 5> myArray;
      myArray = { 0, 1, 2, 3, 4 }; // okay
      myArray = { 9, 8, 7 }; // okay, elements 3 and 4 are set to zero!
      myArray = { 0, 1, 2, 3, 4, 5 }; // not allowed, too many elements in initializer list!
      L'accès aux valeurs de std :: array à l'aide de l'opérateur subscript fonctionne exactement comme prévu:
      Code:
      std::cout << myArray[1];
      myArray[2] = 6;
      Tout comme les tableaux fixes intégrés, l'opérateur en indice ne vérifie pas les limites. Si un index non valide est fourni, de mauvaises choses vont probablement arriver.

      std :: array supporte une seconde forme d'accès à un élément de tableau (la fonction at ()) qui vérifie les limites:
      Code:
      std::array<int, 5> myArray { 9, 7, 5, 3, 1 };
      myArray.at(1) = 6; // array element 1 valid, sets array element 1 to value 6
      myArray.at(9) = 10; // array element 9 is invalid, will throw error
      Dans l'exemple ci-dessus, l'appel à array.at (1) vérifie que l'élément de tableau 1 est valide et, ce qui est vrai, renvoie une référence à l'élément de tableau 1. Nous lui affectons ensuite la valeur 6. Cependant, l'appel à array.at (9) échoue car l'élément de tableau 9 est hors limites pour le tableau. Au lieu de renvoyer une référence, la fonction at () génère une erreur qui termine le programme (remarque: elle lève en fait une exception de type std :: out_of_range - nous traitons des exceptions dans le chapitre 15). Comme il vérifie les limites, at () est plus lent (mais plus sûr) que l'opérateur [].

      std :: array nettoiera lui-même quand il sortira de sa portée, il n’a donc pas besoin d’être nettoyé.

      Taille et tri

      La fonction size () peut être utilisée pour récupérer la longueur du std :: array:
      Code:
      std::array<double, 5> myArray { 9.0, 7.2, 5.4, 3.6, 1.8 };
      std::cout << "length: " << myArray.size();
      Cela imprime:
      length: 5



      Std :: array ne se décomposant pas en pointeur lorsqu'il est transmis à une fonction, la fonction size () fonctionnera même si vous l'appelez de l'intérieur d'une fonction:
      Code:
      #include <iostream>
      #include <array>
      void printLength(const std::array<double, 5> &myArray)
      {
          std::cout << "length: " << myArray.size();
      }
      int main()
      {
          std::array<double, 5> myArray { 9.0, 7.2, 5.4, 3.6, 1.8 };
          printLength(myArray);
          return 0;
      }
      Cela imprime:
      length: 5



      Notez que la bibliothèque standard utilise le terme «taille» pour désigner la longueur du tableau. Ne confondez pas ce résultat avec les résultats de sizeof () sur un tableau natif fixe, qui renvoie la taille réelle du tableau en mémoire (la taille d'un fichier). élément multiplié par la longueur du tableau). Oui, cette nomenclature est incohérente.

      Notez également que nous avons passé std :: array par référence (const). Cela empêche le compilateur de faire une copie du std :: array lorsque le std :: array a été passé à la fonction (pour des raisons de performances).

      Règle: toujours passer std :: array par référence ou par référence const

      Comme la longueur est toujours connue, les boucles for-each (rangeed for) fonctionnent avec std :: array:
      Code:
      std::array<int, 5> myArray { 9, 7, 5, 3, 1 };
      for (auto &element : myArray)
          std::cout << element << ' ';
      Vous pouvez trier std :: array en utilisant std :: sort, qui réside dans l'en-tête de l'algorithme:
      Code:
      #include <iostream>
      #include <array>
      #include <algorithm> // for std::sort
      int main()
      {
          std::array<int, 5> myArray { 7, 3, 1, 9, 5 };
          std::sort(myArray.begin(), myArray.end()); // sort the array forwards
      //    std::sort(myArray.rbegin(), myArray.rend()); // sort the array backwards
          for (const auto &element : myArray)
              std::cout << element << ' ';
          return 0;
      }
      Cela imprime:
      1 3 5 7 9


      La fonction de tri utilise des itérateurs, concept que nous n’avons pas encore abordé. Vous pouvez donc traiter les paramètres comme suit: std :: sort () est un peu magique. Nous allons les expliquer dans la leçon sur les itérateurs.

      Indexer manuellement std :: array via size_type

      Pop quiz: Quel est le problème avec le code suivant?
      Code:
      #include <iostream>
      #include <array>
      int main()
      {
          std::array<int, 5> myArray { 7, 3, 1, 9, 5 };
          // Iterate through the array and print the value of the elements
          for (int i{ 0 }; i < myArray.size(); ++i)
              std::cout << myArray[i] << ' ';
          return 0;
      }
      La réponse est qu’il ya probablement une incompatibilité signée / non signée dans ce code! En raison d’une décision curieuse, la fonction size () et le paramètre d’index de tableau de l’opérateur [] utilisent un type appelé size_type, défini par le standard C ++ en tant que type intégral non signé. Notre compteur / index de boucle (variable i) est un entier signé. Par conséquent, la comparaison i <myArray.size () et l'index de tableau myArray présentent des incohérences de type.

      Chose intéressante, size_type n'est pas un type global (comme int ou std :: size_t). Au contraire, il est défini dans la définition de std :: array (C ++ autorise les types imbriqués). Cela signifie que lorsque nous voulons utiliser size_type, nous devons le préfixer avec le type de tableau complet (pensez à std :: array agissant comme un espace de noms à cet égard). Dans notre exemple ci-dessus, le type de préfixe "size_type" est: std :: array <int, 5> :: size_type!

      Par conséquent, la manière correcte d'écrire le code ci-dessus est la suivante:
      Code:
      #include <iostream>
      #include <array>
      int main()
      {
          std::array<int, 5> myArray { 7, 3, 1, 9, 5 };
          for (std::array<int, 5>::size_type i{ 0 }; i < myArray.size(); ++i) // std::array<int, 5>::size_type is the return type of size()!
              std::cout << myArray[i] << ' ';
          return 0;
      }
      Ce n'est pas très lisible. Un alias de type peut aider un peu:
      Code:
      #include <iostream>
      #include <array>
      int main()
      {
          std::array<int, 5> myArray { 7, 3, 1, 9, 5 };
          using index_t = std::array<int, 5>::size_type;
          for (index_t i{ 0 }; i < myArray.size(); ++i)
              std::cout << myArray[i] << ' ';
          return 0;
      }
      C’est un peu mieux et cette solution offre probablement la meilleure combinaison de correction technique et de lisibilité.

      Dans toutes les implémentations courantes de std :: array, size_type est un typedef pour std :: size_t. Il est donc assez courant de voir les développeurs utiliser plutôt size_t. Bien que techniquement non correct, dans presque toutes les implémentations, cela fonctionnera:
      Code:
      #include <iostream>
      #include <array>
      int main()
      {
          std::array<int, 5> myArray { 7, 3, 1, 9, 5 };
          for (std::size_t i{ 0 }; i < myArray.size(); ++i)
              std::cout << myArray[i] << ' ';
          return 0;
      }
      Une meilleure solution consiste à éviter l'indexation manuelle de std :: array en premier lieu. Au lieu de cela, utilisez si possible des boucles for (ou des itérateurs) basées sur la plage.

      Résumé

      std :: array est un excellent remplacement pour les tableaux fixes intégrés. C’est efficace car il n’utilise pas plus de mémoire que les baies fixes intégrées. Le seul inconvénient réel de std :: array par rapport à un tableau fixe intégré est une syntaxe légèrement plus compliquée, dans laquelle vous devez spécifier explicitement la longueur du tableau (le compilateur ne le calculera pas à partir de l'initialiseur), et problèmes signés / non signés avec la taille et l'indexation. Mais ce ne sont que des petits inconvénients - nous vous recommandons d’utiliser std :: array plutôt que des tableaux fixes intégrés pour toute utilisation de tableau non triviale.
       
      Loading...

      Merci de partager ce post sur facebook

    2. Merci d'aimer notre facebook page

Share This Page