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:
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::rozpocznij | Zwraca iterator do pierwszego elementu danego kontenera. | zaczynać ( pojemnik ) |
| std::koniec | Zwraca iterator do elementu następującego po ostatnim elemencie danego kontenera. | koniec ( pojemnik ) |
| std::rrozpocznij | Zwraca iterator odwrotny do ostatniego elementu danego kontenera. | zacznij ( pojemnik ) |
| std::rend | Zwraca 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.