logo

Iteratory w C++ STL

Jakiś  iterator w C++  jest obiektem przypominającym wskaźnik, który wskazuje element kontenera STL. Zwykle są używane do przeglądania zawartości kontenera STL w C++. Główną zaletą iteratorów STL jest to, że czynią algorytmy STL niezależnymi od typu używanego kontenera. Możemy po prostu przekazać iterator do elementów kontenera zamiast samego kontenera do algorytmów STL.

Deklaracja iteratora

Każdy kontener w C++ STL ma swój własny iterator. Musimy więc zadeklarować iterator jako:



C++
<type>::iterator it; 

Gdzie

  • typ: Typ kontenera, dla którego zadeklarowano iterator.
  • To: Nazwa przypisana do obiektu iteratora.

Następnie możemy go zainicjować, przypisując prawidłowy iterator. Jeśli w momencie delkaracji mamy już iterator do przypisania, możemy pominąć deklarację typu za pomocą automatyczny słowo kluczowe.

C++
auto it = iter 

Gdzie iter to iterator przypisany do nowo utworzonego iteratora it.



Nasz Kurs C++ obejmuje użycie iteratorów w STL, zapewniając zrozumienie, jak przeglądać różne typy kontenerów.

Przykład iteratorów

Poniższy program ilustruje sposób użycia iteratora do poruszania się po kontenerze wektorowym:

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

Wyjście
1 2 3 4 5 

Jak zapewne zauważyłeś, użyliśmy wektor::begin() i wektor::end() funkcjonować. Funkcje te są funkcjami członkowskimi std::vector, które zwracają iterator do pierwszego i jednego elementu po ostatnim elemencie wektora. Używamy iteratorów return do tych funkcji, aby iterować wektory.



Funkcje iteratora kontenera

C++ STL udostępnia pewne funkcje członkowskie w Kontener STL które zwracają iteratory przynajmniej do pierwszego i ostatniego elementu. Te funkcje członkowskie są zdefiniowane w prawie całym kontenerze STL (pozostawiając niektóre kontenery o ograniczonym dostępie, takie jak stos kolejka ) o tej samej nazwie dla zachowania spójności.

Poniższa tabela zawiera listę wszystkich metod zwracających iterator do kontenerów:

Funkcja iteratora

Wartość zwracana

zaczynać()

Zwraca iterator na początek kontenera.

koniec()

Zwraca iterator do elementu teoretycznego tuż za ostatnim elementem kontenera.

cbegin()

Zwraca stały iterator na początek kontenera. Stały iterator nie może modyfikować wartości elementu, na który wskazuje.

kilka()

inaczej, jeśli bash

Zwraca stały iterator do elementu teoretycznego tuż za ostatnim elementem kontenera.

rzacznij()

Zwraca iterator odwrotny na początek kontenera.

oddać()

Zwraca iterator odwrotny do elementu teoretycznego tuż za ostatnim elementem kontenera.

crbegin()

Zwraca stały iterator odwrotny na początek kontenera.

KREDYT ()

Zwraca stały iterator odwrotny do elementu teoretycznego tuż za ostatnim elementem kontenera.

Na przykład jeśli rzecz jest nazwą wektora, możemy użyć powyższych metod, jak pokazano poniżej:

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

Operacje iteratorów

Podobnie jak w przypadku arytmetyki wskaźników, istnieją pewne operacje, które są dozwolone w iteratorach C++. Służą do zapewnienia różnych funkcjonalności, które zwiększają znaczenie iteratorów. Jest 5 ważnych Operacje iteracyjne w C++ :

  • Iteratory dereferencji
  • Iteratory inkrementacyjne/dekrementacyjne
  • Dodawanie/odejmowanie liczby całkowitej do iteratorów
  • Odejmowanie innego iteratora
  • Porównanie iteratorów

Iteratory dereferencji

Operacja wyłuskiwania umożliwia użytkownikom dostęp lub aktualizację wartość elementu wskazywanego przez iterator. Używamy (*) operator pośredni do wyłuskiwania iteratorów, tak jak wskaźników.

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

Gdzie nowa_wartość to nowa wartość przypisana do elementu wskazywanego przez iterator To .

Iteratory inkrementacyjne/dekrementacyjne

Możemy zwiększać lub zmniejszać iterator o 1 za pomocą operatory (++) lub (--). odpowiednio. Operacja zwiększania przenosi iterator do następnego elementu w kontenerze, natomiast operacja zmniejszania przenosi iterator do poprzedniego elementu.

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

Dodawanie/odejmowanie liczby całkowitej do iteratorów

Możemy także dodać lub odjąć wartość całkowitą od iteratorów. Będzie to bardziej iterator następnej lub poprzedniej pozycji zgodnie z dodaną wartością całkowitą.

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

Gdzie int_val to wartości całkowite dodawane lub odejmowane z iteratora To .

Odejmowanie innego iteratora

Możemy odjąć jeden iterator od drugiego, aby znaleźć odległość (lub liczbę elementów) pomiędzy pamięcią, na którą wskazują.

C++
it1 - it2 

Porównanie iteratorów

Możemy także przetestować dwa iteratory tego samego typu względem siebie, aby znaleźć relację między nimi. Możemy używać operatorów relacyjnych, takich jak (==) operatory równości i (!=) nierówności, wraz z innymi operatorami relacyjnymi, takimi jak< > <= >=.

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 

Rodzaje iteratorów w C++

Iteratory STL można podzielić ze względu na operacje, jakie można na nich wykonać. W C++ istnieje 5 głównych typów iteratorów, które wymieniono w poniższej tabeli wraz z obsługiwanymi kontenerami i obsługiwanymi operacjami iteratora.

Iterator

Opis

Obsługiwane kontenery

Obsługiwane operacje

Iterator wejściowy

Jest to iterator jednokierunkowy używany do odczytu wartości.

Strumień wejściowy

Dereferencja przyrostu równości

Iterator wyjściowy

Jest to również iterator jednokierunkowy, ale używany do przypisywania wartości. Nie może uzyskać dostępu do wartości.

Strumień wyjściowy

Dereferencja (tylko zapis) Przyrost

Iteratory do przodu

Może uzyskiwać dostęp do wartości i przypisywać je. Jest to połączenie iteratora wejściowego i wyjściowego.

forward_list unordered_map unordered_set

Dereferencja przyrostu równości

Iteratory dwukierunkowe

Może poruszać się w obu kierunkach, do przodu lub do tyłu. Kontenery takie jak zestaw list i multimap obsługują iteratory dwukierunkowe.

lista zestaw map zestaw wielu map

Dereferencja zwiększania/zmniejszania równości

Iteratory o dostępie swobodnym

Iteratory o dostępie swobodnym to iteratory, których można używać do uzyskiwania dostępu do elementów na odległość od elementu, na który wskazują, oferując tę ​​samą funkcjonalność co wskaźniki.

wektor deque ciąg tablicy

okno.otwórz javascript

Wszystko

Jak mogliśmy zauważyć z powyższej tabeli, poza iteratorami wejściowymi i wyjściowymi gdy schodzimy w dół tabeli, typ iteratora zawiera funkcje powyższego iteratora wraz z kilkoma nowymi funkcjami.

Adaptery iteratorów

Adaptery iteratorów w języku C++ to specjalny typ iteratorów zbudowanych w oparciu o tradycyjne iteratory w celu zapewnienia wyspecjalizowanej funkcjonalności. W C++ istnieje wiele adapterów iteratorów, niektóre z nich podano poniżej:

Typ adapterów iteratora

Opis

Odwrotny iterator

Iterator odwrotny jest zbudowany na operatorze dwukierunkowym lub wyższym i umożliwia użytkownikom przemieszczanie się po kontenerze w odwrotnym kierunku.

Iteratory strumieniowe

Iteratory strumienia, mianowicie iteratory istream i ostream, są zbudowane odpowiednio na iteratorach wejściowych i wyjściowych. Te iteratory pozwalają użytkownikom używać strumieni jako kontenerów.

Przenieś iteratory

Iteratory przenoszenia służą do wprowadzenia semantyki przenoszenia w algorytmach STL. Iteratory przenoszenia przenoszą własność skopiowanych danych kontenera do kontenera kopiującego bez tworzenia dodatkowych kopii.

Iterator wstawiający

Iteratory wstawiające umożliwiają wstawienie danych elementów w dowolnym miejscu kontenera. W C++ istnieją trzy iteratory wstawiające:

  1. back_insert_iterator: Wkładki z tyłu pojemnika.
  2. front_insert_iterator: Wstawki z przodu pojemnika.
  3. wstaw_iterator: Wstawia się w dowolnym miejscu pojemnika.

Te iteratory można utworzyć za pomocą back_inserter() front_inserter() wstawić() funkcje w C++.

Funkcje narzędziowe iteratora w C++

C++ STL udostępnia różne funkcje upraszczające pracę z iteratorami. Są one wymienione w poniższej tabeli:

Funkcjonować Opis Składnia
std::zaliczka Przesuwa iterator o określoną liczbę pozycji. osiągnięcie ( to n )
std::następny Zwraca iterator znajdujący się o określoną liczbę pozycji przed danym iteratorem. Następny ( to n )
Std :: Poprzednie Zwraca iterator będący określoną liczbą pozycji za danym iteratorem. poprzednie ( to n )
std::odległość Zwraca liczbę elementów pomiędzy dwoma iteratorami. dystans ( to1 to2 )
std::rozpocznijZwraca iterator do pierwszego elementu danego kontenera. zaczynać ( pojemnik )
std::koniecZwraca iterator do elementu następującego po ostatnim elemencie danego kontenera. koniec ( pojemnik )
std::rrozpocznijZwraca iterator odwrotny do ostatniego elementu danego kontenera. zacznij ( pojemnik )
std::rendZwraca iterator odwrotny do elementu poprzedzającego pierwszy element danego kontenera. sprawia ( pojemnik )
std::wstawacz Tworzy iterator wstawiania, który wstawia elementy do kontenera w określonej pozycji. wkładacz ( pozycja kontenera )
std::back_inserter Tworzy iterator wstawiania wstecznego, który dołącza elementy na końcu kontenera. back_inserter ( pojemnik )
std::front_inserter Tworzy iterator wstawiania z przodu, który wstawia elementy z przodu kontenera. wkład_frontowy ( pojemnik )

Zastosowania iteratorów z przykładami

Iteratory są szeroko stosowane w C++ do wielu różnych celów podczas pracy z kontenerami i algorytmami STL. Poniżej znajdują się niektóre podstawowe zastosowania iteratorów w C++ wraz z przykładami ich kodu:

Przemierzanie kontenerów

Najbardziej podstawowym zastosowaniem iteratorów jest przechodzenie przez kontenery STL. W tym przypadku używamy funkcji Begin() i End(), aby iteratory Begin i End przemierzały cały kontener. Zasadniczo zwiększamy iterator początku, aż nie będzie on równy końcowi.

Przykład

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

Wyjście
10 20 30 40 50 

Jak pokazano w powyższym kodzie, przechodzimy przez ustawiony kontener. Podobnie możemy zastosować to samo podejście do przechodzenia przez dowolny kontener.

Odwracanie kontenera

Iteratory odwrotne umożliwiają przechodzenie przez kontener od końca do początku bez konieczności ręcznej obsługi odwrócenia.

Przykład

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

Wyjście
50 40 30 20 10 

Algorytmy niezależne od kontenera

Iteratory umożliwiają algorytmom współpracę z dowolnym typem kontenera, dzięki czemu funkcje takie jak std::sort() std::find() i std::for_each() są bardziej elastyczne. Zamiast rzeczywistego kontenera możesz przekazywać iteratory.

Przykład

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

Wyjście
10s in Vector: 2 10s in Multiset: 3

Dodatkowe zastosowania iteratorów

Istnieje więcej zastosowań iteratorów STL:

  • Obliczanie odległości: Użycie iteratorów std::distance() pomaga obliczyć liczbę elementów pomiędzy dwiema pozycjami w kontenerze.
  • Iteracja strumienia: Iteratory strumieni pozwalają traktować strumienie wejścia/wyjścia jak kontenery, co ułatwia odczytywanie i zapisywanie strumieni przy użyciu algorytmów STL.
  • Przenieś semantykę w algorytmach STL: Iteratory przenoszenia wprowadzają semantykę przenoszenia w algorytmach STL, która pomaga zwiększyć wydajność i efektywność poprzez uniknięcie niepotrzebnego kopiowania. Dane zostaną przeniesione zgodnie z zasadami semantyki przenoszenia.
  • Niestandardowe iteratory dla struktur danych: Niestandardowe iteratory można zaimplementować dla struktur danych innych niż STL, takich jak drzewa lub wykresy, aby zapewnić obsługę algorytmów STL i wielu innych funkcji. Być może będziemy musieli przestrzegać kilku zestawów zasad i konwencji, aby zapewnić prawidłowe zwiększanie, zmniejszanie i inne operacje.