logo

Iteratoren in C++ STL

Ein  Iterator in C++  ist ein zeigerähnliches Objekt, das auf ein Element des STL-Containers zeigt. Sie werden im Allgemeinen verwendet, um den Inhalt des STL-Containers in C++ zu durchlaufen. Der Hauptvorteil von STL-Iteratoren besteht darin, dass sie die STL-Algorithmen unabhängig vom Typ des verwendeten Containers machen. Wir können einfach den Iterator an die Containerelemente übergeben, anstatt den Container selbst an die STL-Algorithmen.

Iterator-Deklaration

Jeder Container in C++ STL verfügt über einen eigenen Iterator. Also müssen wir einen Iterator wie folgt deklarieren:



C++
<type>::iterator it; 

Wo

  • Typ: Typ des Containers, für den der Iterator deklariert ist.
  • Es: Dem Iteratorobjekt zugewiesener Name.

Wir können es dann initialisieren, indem wir einen gültigen Iterator zuweisen. Wenn wir zum Zeitpunkt der Deklaration bereits einen Iterator zuweisen möchten, können wir die Typdeklaration mit überspringen Auto Stichwort.

C++
auto it = iter 

Wo iter ist der Iterator, der dem neu erstellten It-Iterator zugewiesen ist.



Unser C++-Kurs behandelt die Verwendung von Iteratoren in der STL und stellt sicher, dass Sie verstehen, wie Sie verschiedene Containertypen durchlaufen.

Beispiel für Iteratoren

Das folgende Programm veranschaulicht, wie der Iterator zum Durchlaufen des Vektorcontainers verwendet wird:

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; } 

Ausgabe
1 2 3 4 5 

Wie Sie vielleicht bemerkt haben, haben wir verwendet vector::begin() und vector::end() Funktion. Diese Funktionen sind die Mitgliedsfunktionen von std::vector, die den Iterator zum ersten und ein Element nach dem letzten Element des Vektors zurückgeben. Wir verwenden die Iteratoren return be dieser Funktionen, um die Vektoren zu iterieren.



Container-Iterator-Funktionen

C++ STL bietet einige Mitgliedsfunktionen in STL-Container die die Iteratoren mindestens zum ersten und letzten Element zurückgeben. Diese Mitgliedsfunktionen sind in fast allen STL-Containern definiert (wobei einige Container mit eingeschränktem Zugriff übrig bleiben, z Stapel Warteschlange ) mit demselben Namen aus Gründen der Konsistenz.

Die folgende Tabelle listet alle Methoden auf, die den Iterator an die Container zurückgeben:

Iteratorfunktion

Rückgabewert

beginnen()

Gibt einen Iterator an den Anfang des Containers zurück.

Ende()

Gibt einen Iterator zum theoretischen Element direkt nach dem letzten Element des Containers zurück.

cbegin()

Gibt einen konstanten Iterator an den Anfang des Containers zurück. Ein konstanter Iterator kann den Wert des Elements, auf das er zeigt, nicht ändern.

ein paar()

Algorithmus für RSA

Gibt einen konstanten Iterator zum theoretischen Element direkt nach dem letzten Element des Containers zurück.

rbegin()

Gibt einen umgekehrten Iterator zum Anfang des Containers zurück.

machen()

Gibt einen umgekehrten Iterator zum theoretischen Element direkt nach dem letzten Element des Containers zurück.

crbegin()

Gibt einen konstanten Reverse-Iterator zum Anfang des Containers zurück.

CREND ()

Gibt einen konstanten umgekehrten Iterator zum theoretischen Element direkt nach dem letzten Element des Containers zurück.

Zum Beispiel wenn eine Sache ist der Name des Vektors, dann können wir die oben genannten Methoden wie unten gezeigt verwenden:

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

Iteratoroperationen

Genau wie bei der Zeigerarithmetik gibt es einige Operationen, die für C++-Iteratoren zulässig sind. Sie werden verwendet, um verschiedene Funktionalitäten bereitzustellen, was die Bedeutung von Iteratoren erhöht. Es sind 5 gültig Iteratoroperationen in C++ :

  • Dereferenzierung von Iteratoren
  • Inkrementierende/dekrementierende Iteratoren
  • Addieren/Subtrahieren von Ganzzahlen zu Iteratoren
  • Einen anderen Iterator subtrahieren
  • Vergleich von Iteratoren

Dereferenzierung von Iteratoren

Der Dereferenzierungsvorgang ermöglicht es den Benutzern Zugriff oder Aktualisierung der Wert des Elements, auf das der Iterator zeigt. Wir nutzen die (*) Indirektionsoperator um Iteratoren genau wie Zeiger zu dereferenzieren.

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

Wo neuer_Wert ist der neue Wert, der dem Element zugewiesen wird, auf das der Iterator zeigt Es .

Inkrementierende/dekrementierende Iteratoren

Wir können den Iterator mit um 1 erhöhen oder dekrementieren (++) oder (--) Operatoren jeweils. Die Inkrementierungsoperation verschiebt den Iterator zum nächsten Element im Container, während die Dekrementierungsoperation den Iterator zum vorherigen Element verschiebt.

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

Addieren/Subtrahieren von Ganzzahlen zu Iteratoren

Wir können den Iteratoren auch einen ganzzahligen Wert hinzufügen oder davon subtrahieren. Je nach hinzugefügtem Ganzzahlwert wird der Iterator an die nächste oder vorherige Position verschoben.

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

Wo int_val ist der ganzzahlige Wert, der vom Iterator addiert oder subtrahiert wird Es .

Einen anderen Iterator subtrahieren

Wir können einen Iterator von einem anderen subtrahieren, um den Abstand (oder die Anzahl der Elemente) zwischen dem Speicher zu ermitteln, auf den sie zeigen.

C++
it1 - it2 

Vergleich von Iteratoren

Wir können auch die beiden Iteratoren desselben Typs gegeneinander testen, um die Beziehung zwischen ihnen herauszufinden. Wir können die relationalen Operatoren wie (==) Gleichheits- und (!=) Ungleichheitsoperatoren zusammen mit anderen relationalen Operatoren wie verwenden< > <= >=.

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 

Arten von Iteratoren in C++

STL-Iteratoren können anhand der Operationen, die auf ihnen ausgeführt werden können, unterteilt werden. In C++ gibt es fünf Haupttypen von Iteratoren, die in der folgenden Tabelle zusammen mit unterstützten Containern und unterstützten Iteratoroperationen aufgeführt sind.

Iterator

Beschreibung

Unterstützte Container

Unterstützte Operationen

Eingabe-Iterator

Es handelt sich um einen Einweg-Iterator, der zum Lesen der Werte verwendet wird.

Eingabestream

Dereferenzierung der Inkrementgleichheit

Ausgabe-Iterator

Es handelt sich ebenfalls um einen Einweg-Iterator, der jedoch zum Zuweisen der Werte verwendet wird. Es kann nicht auf die Werte zugegriffen werden.

Ausgabestream

Dereferenzierung (nur Schreiben) Inkrementieren

Forward-Iteratoren

Es kann auf die Werte zugreifen und diese auch zuweisen. Es ist die Kombination aus Eingabe- und Ausgabeiterator.

Forward_list unordered_map unordered_set

Dereferenzierung der Inkrementgleichheit

Bidirektionale Iteratoren

Es kann sich in beide Richtungen vorwärts oder rückwärts bewegen. Die Container wie List Set und Multimap unterstützen bidirektionale Iteratoren.

Listen Sie den Kartensatz Multimap Multiset auf

Dereferenzierung der Inkrement-/Dekrement-Gleichheit

Iteratoren mit wahlfreiem Zugriff

Iteratoren mit wahlfreiem Zugriff sind Iteratoren, die verwendet werden können, um auf Elemente in einer Entfernung von dem Element zuzugreifen, auf das sie zeigen, und die dieselbe Funktionalität wie Zeiger bieten.

Vektor-Deque-Array-String

Operatoren in der Python-Programmierung

Alle

Wie wir vielleicht anhand der obigen Tabelle bemerkt haben, abgesehen von den Eingabe- und Ausgabeiteratoren Wenn wir die Tabelle durchgehen, enthält der Iteratortyp die Funktionen des oben genannten Iterators sowie einige neue Funktionen.

Iterator-Adapter

Iteratoradapter in C++ sind spezielle Iteratortypen, die über herkömmlichen Iteratoren aufgebaut sind, um spezielle Funktionen bereitzustellen. Es gibt viele Iterator-Adapter in C++, von denen einige unten aufgeführt sind:

Iterator-Adaptertyp

Beschreibung

Reverse-Iterator

Der umgekehrte Iterator basiert auf einem bidirektionalen oder höheren Operatortyp und ermöglicht es Benutzern, den Container in umgekehrter Richtung zu durchlaufen.

Stream-Iteratoren

Die Stream-Iteratoren, nämlich istream- und ostream-Iteratoren, basieren auf den Eingabe- bzw. Ausgabe-Iteratoren. Diese Iteratoren ermöglichen es den Benutzern, die Streams als Container zu verwenden.

Iteratoren verschieben

Move-Iteratoren werden verwendet, um die Move-Semantik in STL-Algorithmen einzuführen. Die Verschiebungsiteratoren verschieben den Besitz der kopierten Containerdaten auf den Kopiercontainer, ohne zusätzliche Kopien zu erstellen.

Inserter-Iterator

Mit den Insertor-Iteratoren können Sie die angegebenen Elemente an einer bestimmten Position im Container einfügen. In C++ gibt es drei Insertor-Iteratoren:

  1. back_insert_iterator: Einsätze an der Rückseite des Behälters.
  2. front_insert_iterator: Einsätze an der Vorderseite des Behälters.
  3. insert_iterator: Wird an einer beliebigen Stelle im Behälter eingefügt.

Diese Iteratoren können mit erstellt werden back_inserter() front_inserter() einfügen() Funktionen in C++.

Iterator-Dienstprogrammfunktionen in C++

C++ STL bietet verschiedene Funktionen, um die Arbeit mit Iteratoren zu vereinfachen. Sie sind in der folgenden Tabelle aufgeführt:

Funktion Beschreibung Syntax
std::advance Verschiebt einen Iterator um eine bestimmte Anzahl von Positionen. Vorauszahlung ( es n )
std::next Gibt den Iterator zurück, der eine angegebene Anzahl von Positionen vor dem angegebenen Iterator liegt. nächste ( es n )
Std :: Vorher Gibt den Iterator zurück, der eine angegebene Anzahl von Positionen hinter dem angegebenen Iterator liegt. vorh ( es n )
std::distanz Gibt die Anzahl der Elemente zwischen zwei Iteratoren zurück. Distanz ( it1 it2 )
std::beginGibt einen Iterator zum ersten Element des angegebenen Containers zurück. beginnen ( Container )
std::endGibt einen Iterator für das Element zurück, das auf das letzte Element des angegebenen Containers folgt. Ende ( Container )
std::rbeginGibt einen umgekehrten Iterator zum letzten Element des angegebenen Containers zurück. rbeginnen ( Container )
std::rendGibt einen umgekehrten Iterator zu dem Element zurück, das dem ersten Element des angegebenen Containers vorangeht. macht ( Container )
std::inserter Erstellt einen Einfüge-Iterator, der Elemente an einer angegebenen Position in einen Container einfügt. Einfügemaschine ( Behälterposition )
std::back_inserter Erstellt einen Back-Insert-Iterator, der Elemente an das Ende eines Containers anhängt. back_inserter ( Container )
std::front_inserter Erstellt einen Front-Insert-Iterator, der Elemente an der Vorderseite eines Containers einfügt. front_inserter ( Container )

Anwendungen von Iteratoren mit Beispielen

Iteratoren werden in C++ häufig für viele verschiedene Zwecke bei der Arbeit mit STL-Containern und -Algorithmen verwendet. Im Folgenden sind einige Hauptanwendungen von Iteratoren in C++ mit ihren Codebeispielen aufgeführt:

Durchqueren von Containern

Das Durchlaufen von STL-Containern ist die grundlegendste Anwendung von Iteratoren. Hier verwenden wir die Funktionen begin() und end(), um die Anfangs- und End-Iteratoren dazu zu bringen, den gesamten Container zu durchlaufen. Grundsätzlich erhöhen wir den Anfangsiterator so lange, bis er nicht mehr dem Ende entspricht.

Beispiel

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; } 

Ausgabe
10 20 30 40 50 

Wie im obigen Code gezeigt, durchlaufen wir den Set-Container. Ebenso können wir den gleichen Ansatz verwenden, um jeden Container zu durchlaufen.

Einen Container umkehren

Mit Reverse-Iteratoren können Sie einen Container vom Ende zum Anfang durchlaufen, ohne die Umkehrung manuell durchführen zu müssen.

Beispiel

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; } 

Ausgabe
50 40 30 20 10 

Containerunabhängige Algorithmen

Iteratoren ermöglichen es Algorithmen, mit jedem Containertyp zu arbeiten, wodurch Funktionen wie std::sort(), std::find() und std::for_each() flexibler werden. Sie können Iteratoren anstelle des eigentlichen Containers übergeben.

Beispiel

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; } 

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

Zusätzliche Anwendungen von Iteratoren

Es gibt weitere Anwendungen von STL-Iteratoren:

  • Entfernungsberechnung: Die Verwendung von std::distance()-Iteratoren hilft bei der Berechnung der Anzahl der Elemente zwischen zwei Positionen in einem Container.
  • Stream-Iteration: Stream-Iteratoren ermöglichen es Ihnen, Eingabe-/Ausgabe-Streams wie Container zu behandeln, was das Lesen aus und Schreiben in Streams mithilfe von STL-Algorithmen erleichtert.
  • Bewegungssemantik in STL-Algorithmen: Move-Iteratoren führen die Move-Semantik in STL-Algorithmen ein, was zur Steigerung der Leistung und Effizienz beiträgt, indem unnötiges Kopieren vermieden wird. Die Daten werden gemäß den Regeln der Verschiebungssemantik verschoben.
  • Benutzerdefinierte Iteratoren für Datenstrukturen: Benutzerdefinierte Iteratoren können für Nicht-STL-Datenstrukturen wie Bäume oder Diagramme implementiert werden, um die Unterstützung für STL-Algorithmen und viele andere Funktionen bereitzustellen. Möglicherweise müssen wir einige Regeln und Konventionen befolgen, um ordnungsgemäße Inkrementierungs-, Dekrementierungs- und andere Vorgänge bereitzustellen.