logo

Itérateurs en C++ STL

Un  itérateur en C++  est un objet de type pointeur qui pointe vers un élément du conteneur STL. Ils sont généralement utilisés pour parcourir le contenu du conteneur STL en C++. Le principal avantage des itérateurs STL est qu'ils rendent les algorithmes STL indépendants du type de conteneur utilisé. Nous pouvons simplement transmettre l'itérateur aux éléments du conteneur au lieu du conteneur lui-même aux algorithmes STL.

Déclaration de l'itérateur

Chaque conteneur en C++ STL possède son propre itérateur. Nous devons donc déclarer un itérateur comme :



C++
<type>::iterator it; 

  • taper: Type de conteneur pour lequel l'itérateur est déclaré.
  • il: Nom attribué à l’objet itérateur.

Nous pouvons ensuite l'initialiser en attribuant un itérateur valide. Si nous avons déjà un itérateur à attribuer au moment de la déclaration, nous pouvons ignorer la déclaration de type en utilisant le auto mot-clé.

C++
auto it = iter 

itérer est l'itérateur affecté à l'itérateur it nouvellement créé.



Notre Cours C++ couvre l'utilisation des itérateurs dans la STL en vous assurant de comprendre comment parcourir différents types de conteneurs.

Exemple d'itérateurs

Le programme ci-dessous illustre comment utiliser l'itérateur pour parcourir le conteneur vectoriel :

C++
#include    using namespace std; int main() {  vector<int> v = {1 2 3 4 5};  // Defining an iterator pointing to  // the beginning of the vector  vector<int>::iterator first =  v.begin();  // Defining an iterator pointing  // to the end of the vector  vector<int>::iterator last =  v.end();    // Iterating the whole vector  while(first != last) {  cout << *first << ' ';  first++;  }  return 0; } 

Sortir
1 2 3 4 5 

Comme vous l'avez peut-être remarqué, nous avons utilisé vecteur :: début () et vecteur :: fin () fonction. Ces fonctions sont les fonctions membres de std::vector qui renvoient l'itérateur au premier et à un élément après le dernier élément du vecteur. Nous utilisons les itérateurs de retour de ces fonctions pour itérer les vecteurs.



Fonctions de l'itérateur de conteneur

C++ STL fournit certaines fonctions membres dans Conteneur STL qui renvoient les itérateurs au moins au premier et au dernier élément. Ces fonctions membres sont définies dans presque tous les conteneurs STL (en laissant certains conteneurs à accès limité comme empiler file d'attente ) avec le même nom par souci de cohérence.

Le tableau suivant répertorie toutes les méthodes qui renvoient l'itérateur aux conteneurs :

Fonction itérateur

Valeur de retour

commencer()

Renvoie un itérateur au début du conteneur.

fin()

Renvoie un itérateur à l'élément théorique juste après le dernier élément du conteneur.

ccommencer()

Renvoie un itérateur constant au début du conteneur. Un itérateur constant ne peut pas modifier la valeur de l'élément vers lequel il pointe.

quelques()

liste de latex

Renvoie un itérateur constant à l'élément théorique juste après le dernier élément du conteneur.

rcommencer()

Renvoie un itérateur inverse au début du conteneur.

rend()

Renvoie un itérateur inverse à l'élément théorique juste après le dernier élément du conteneur.

crbegin()

Renvoie un itérateur inverse constant au début du conteneur.

CREND ()

Renvoie un itérateur inverse constant à l'élément théorique juste après le dernier élément du conteneur.

Par exemple si une chose est le nom du vecteur, nous pouvons alors utiliser les méthodes ci-dessus comme indiqué ci-dessous :

C++
vec.begin() vec.rbegin() vec.cbegin() vec.crbegin() vec.end() vec.rend()  vec.cend() vec.crend() 

Opérations des itérateurs

Tout comme l’arithmétique des pointeurs, certaines opérations sont autorisées sur les itérateurs C++. Ils sont utilisés pour fournir différentes fonctionnalités qui augmentent l’importance des itérateurs. Il y en a 5 valides opérations d'itérateur en C++ :

  • Déréférencement des itérateurs
  • Itérateurs d'incrémentation/décrémentation
  • Ajout/soustraction d'entier aux itérateurs
  • Soustraire un autre itérateur
  • Comparaison des itérateurs

Déréférencement des itérateurs

L'opération de déréférencement permet aux utilisateurs de accès ou mise à jour la valeur de l'élément pointé par l'itérateur. Nous utilisons le (*) opérateur d'indirection pour déréférencer les itérateurs tout comme les pointeurs.

C++
// Access *it; // Update *it = new_val;  

nouveau_val est la nouvelle valeur attribuée à l'élément pointé par l'itérateur il .

Itérateurs d'incrémentation/décrémentation

Nous pouvons incrémenter ou décrémenter l'itérateur de 1 en utilisant Opérateurs (++) ou (--) respectivement. L'opération d'incrémentation déplace l'itérateur vers l'élément suivant dans le conteneur tandis que l'opération de décrémentation déplace l'itérateur vers l'élément précédent.

C++
it++; // post-increment ++it; // pre-increment it--; // post-decrement --it; // pre-decrement 

Ajout/soustraction d'entier aux itérateurs

Nous pouvons également ajouter ou soustraire une valeur entière aux itérateurs. Il s'agira de la position suivante ou précédente de l'itérateur en fonction de la valeur entière ajoutée.

C++
// Addition it + int_val;  // Subtraction it - int_val;  

int_val sont les valeurs entières qui sont ajoutées ou soustraites à l'itérateur il .

Soustraire un autre itérateur

Nous pouvons soustraire un itérateur d'un autre pour trouver la distance (ou le nombre d'éléments) entre la mémoire vers laquelle ils pointent.

C++
it1 - it2 

Comparaison des itérateurs

Nous pouvons également tester les deux itérateurs du même type l’un contre l’autre pour trouver la relation entre eux. Nous pouvons utiliser les opérateurs relationnels comme les opérateurs d'égalité (==) et d'inégalité (!=) ainsi que d'autres opérateurs relationnels tels que< > <= >=.

C++
it1 != it2 // Equal to it1 == it2 // Not equal to it1 > it2 // Greater than it1 < it2 // Less than it1 >= it2 // Greater than equal to it1 <= it2 // Less than equal to 

Types d'itérateurs en C++

Les itérateurs STL peuvent être divisés en fonction des opérations qui peuvent être effectuées sur eux. Il existe 5 principaux types d'itérateurs en C++, répertoriés dans le tableau ci-dessous, ainsi que les conteneurs et les opérations d'itérateur pris en charge.

Itérateur

Description

Conteneurs pris en charge

Opérations prises en charge

Itérateur d'entrée

Il s'agit d'un itérateur unidirectionnel utilisé pour lire les valeurs.

Flux d'entrée

Déréférencement de l'égalité des incréments

Itérateur de sortie

C'est également un itérateur unidirectionnel mais utilisé pour attribuer les valeurs. Il ne peut pas accéder aux valeurs.

Flux de sortie

Déréférencement (écriture uniquement) Incrément

Itérateurs avant

Il peut accéder et attribuer les valeurs. C'est la combinaison des itérateurs d'entrée et de sortie.

forward_list unordered_map unordered_set

Déréférencement de l'égalité des incréments

Itérateurs bidirectionnels

Il peut se déplacer dans les deux sens, en avant ou en arrière. Les conteneurs comme list set et multimap prennent en charge les itérateurs bidirectionnels.

liste ensemble de cartes multicarte multiensemble

Déréférencement de l'égalité d'incrémentation/décrémentation

Itérateurs à accès aléatoire

Les itérateurs à accès aléatoire sont des itérateurs qui peuvent être utilisés pour accéder à des éléments éloignés de l'élément vers lequel ils pointent, offrant les mêmes fonctionnalités que les pointeurs.

chaîne de tableau deque vectorielle

livecricket.is

Tous

Comme nous l'avons peut-être remarqué dans le tableau ci-dessus, en dehors des itérateurs d'entrée et de sortie Au fur et à mesure que nous parcourons le tableau, le type d'itérateur contient les fonctionnalités de l'itérateur ci-dessus ainsi que quelques nouvelles fonctionnalités.

Adaptateurs d'itérateur

Les adaptateurs d’itérateurs en C++ sont un type spécial d’itérateurs construits sur les itérateurs traditionnels pour fournir des fonctionnalités spécialisées. Il existe de nombreux adaptateurs d'itérateurs en C++, dont certains sont indiqués ci-dessous :

Type d'adaptateurs d'itérateur

Description

Itérateur inverse

L'itérateur inverse est construit sur un type d'opérateur bidirectionnel ou supérieur et permet aux utilisateurs de parcourir le conteneur dans le sens inverse.

Itérateurs de flux

Les itérateurs de flux, à savoir les itérateurs istream et ostream, sont construits respectivement sur les itérateurs d'entrée et de sortie. Ces itérateurs permettent aux utilisateurs d'utiliser les flux comme conteneurs.

Déplacer les itérateurs

Les itérateurs de déplacement sont utilisés pour introduire la sémantique de déplacement dans les algorithmes STL. Les itérateurs de déplacement déplacent la propriété des données du conteneur copiées vers le conteneur de copie sans créer de copies supplémentaires.

Itérateur d'insertion

Les itérateurs d'insertion vous permettent d'insérer les éléments donnés à une certaine position dans le conteneur. Il existe trois itérateurs d'insertion en C++ :

  1. back_insert_iterator : Inserts à l'arrière du conteneur.
  2. front_insert_iterator : Inserts à l'avant du conteneur.
  3. insert_iterator : S'insère n'importe où dans le conteneur.

Ces itérateurs peuvent être créés en utilisant back_inserter() front_inserter() insérer() fonctions en C++.

Fonctions utilitaires d'itérateur en C++

C++ STL fournit les différentes fonctions pour simplifier le travail avec les itérateurs. Ils sont répertoriés dans le tableau ci-dessous :

Fonction Description Syntaxe
std :: avance Avance un itérateur d’un nombre spécifique de positions. avance ( ça n )
std :: suivant Renvoie l'itérateur qui a un nombre spécifié de positions en avance sur l'itérateur donné. suivant ( ça n )
Std :: Précédent Renvoie l'itérateur qui se trouve à un nombre spécifié de positions derrière l'itérateur donné. précédent ( ça n )
std :: distance Renvoie le nombre d'éléments entre deux itérateurs. distance ( il1 il2 )
std :: commencerRenvoie un itérateur vers le premier élément du conteneur donné. commencer ( récipient )
std :: finRenvoie un itérateur à l'élément suivant le dernier élément du conteneur donné. fin ( récipient )
std :: rbeginRenvoie un itérateur inverse vers le dernier élément du conteneur donné. commencer ( récipient )
std :: renduRenvoie un itérateur inverse à l'élément précédant le premier élément du conteneur donné. rend ( récipient )
std :: inserteur Crée un itérateur d'insertion qui insère des éléments dans un conteneur à une position spécifiée. inséreuse ( position du conteneur )
std :: back_inserter Crée un itérateur d'insertion arrière qui ajoute des éléments à la fin d'un conteneur. back_inserter ( récipient )
std :: front_inserter Crée un itérateur d'insertion avant qui insère des éléments à l'avant d'un conteneur. front_inserter ( récipient )

Applications des itérateurs avec exemples

Les itérateurs sont largement utilisés en C++ à de nombreuses fins différentes tout en travaillant avec des conteneurs et des algorithmes STL. Voici quelques applications principales des itérateurs en C++ avec leurs exemples de code :

Traversée des conteneurs

La traversée des conteneurs STL est l'application la plus basique des itérateurs. En cela, nous utilisons les fonctions begin() et end() pour que les itérateurs de début et de fin parcourent l'ensemble du conteneur. Fondamentalement, nous continuons à incrémenter l'itérateur de début jusqu'à ce qu'il ne soit pas égal à la fin.

Exemple

C++
#include    using namespace std; int main() {  set<int> s = {10 20 30   40 50};  // Iterator to the beginning   // of the set  auto it = s.begin();  // Iterating through the   // entire set  while (it != s.end()) {    // Dereferencing iterator   // to access value  cout << *it << ' ';    // Incrementing the   // iterator  it++;  }    return 0; } 

Sortir
10 20 30 40 50 

Comme le montre le code ci-dessus, nous parcourons le conteneur défini. De même, nous pouvons utiliser la même approche pour parcourir n’importe quel conteneur.

Inverser un conteneur

Les itérateurs inversés vous permettent de parcourir un conteneur de la fin au début sans avoir à gérer manuellement l'inversion.

Exemple

C++
#include    using namespace std; int main() {  vector<int> vec = {10 20 30   40 50};  // Defining reverse iterators   // pointing to the reverse   // beginning of vec  auto it = vec.rbegin();  // Iterating the whole   // vector in reverse  while (it != vec.rend()) {  cout << *it << ' ';  it++;  }  return 0; } 

Sortir
50 40 30 20 10 

Algorithmes indépendants des conteneurs

Les itérateurs permettent aux algorithmes de fonctionner avec n'importe quel type de conteneur, rendant les fonctions comme std::sort() std::find() et std::for_each() plus flexibles. Vous pouvez transmettre des itérateurs au lieu du conteneur réel.

Exemple

C++
#include    using namespace std; int main() {  vector<int> vec = {30 10 40   10 50};  multiset<int> ms = {10 30 10   20 40 10};  // Using the std::count() algorithm to count  // the number of occurences of 10 in vector  // and multiset using iterator  cout << '10s in Vector: '   << count(vec.begin()  vec.end() 10) << endl;  cout << '10s in Multiset: '   << count(ms.begin()  ms.end() 10);  return 0; } 

Sortir
10s in Vector: 2 10s in Multiset: 3

Applications supplémentaires des itérateurs

Il existe d'autres applications des itérateurs STL :

  • Calcul des distances : L'utilisation des itérateurs std::distance() permet de calculer le nombre d'éléments entre deux positions dans un conteneur.
  • Itération de flux : Les itérateurs de flux vous permettent de traiter les flux d'entrée/sortie comme des conteneurs, ce qui facilite la lecture et l'écriture dans les flux à l'aide d'algorithmes STL.
  • Déplacer la sémantique dans les algorithmes STL : Les itérateurs de déplacement introduisent la sémantique de déplacement dans les algorithmes STL, ce qui contribue à augmenter les performances et l'efficacité en évitant les copies inutiles. Les données seront déplacées selon les règles de la sémantique de déplacement.
  • Itérateurs personnalisés pour les structures de données : Des itérateurs personnalisés peuvent être implémentés pour les structures de données non STL telles que des arbres ou des graphiques afin de fournir la prise en charge des algorithmes STL et de nombreuses autres fonctionnalités. Nous devrons peut-être suivre quelques ensembles de règles et de conventions pour fournir des opérations de décrémentation et d'incrémentation appropriées.