Iteratory

Iterator to obiekt, który może iterować elementy w kontenerze biblioteki standardowej języka C++ i zapewnić dostęp do poszczególnych elementów. Kontenery biblioteki standardowej języka C++ zapewniają iteratory, dzięki czemu algorytmy mogą uzyskiwać dostęp do swoich elementów w standardowy sposób bez konieczności zajmowania się typem kontenera, w jakim są przechowywane elementy.

Można używać iteratorów jawnie przy użyciu funkcji członkowskich i globalnych, takich jak i i, takich jak begin()++ iend(), -- aby przejść do przodu lub do tyłu. Można również używać iteratorów niejawnie z pętlą range-for lub (dla niektórych typów iteratorów) operatorem []indeksu dolnego .

W standardowej bibliotece języka C++ początek sekwencji lub zakresu jest pierwszym elementem. Koniec sekwencji lub zakresu jest zawsze definiowany jako jeden obok ostatniego elementu. Funkcje begin globalne i end zwracają iteratory do określonego kontenera. Typowa pętla iteratora jawnego dla wszystkich elementów w kontenerze wygląda następująco:

vector<int> vec{ 0,1,2,3,4 };
for (auto it = begin(vec); it != end(vec); it++)
{
    // Access element using dereference operator
    cout << *it << " ";
}

To samo można zrobić bardziej po prostu za pomocą pętli range-for:

for (auto num : vec)
{
    // no dereference operator
    cout << num << " ";
}

Istnieje pięć kategorii iteratorów. W kolejności zwiększania mocy kategorie to:

  • Dane wyjściowe. IteratorX danych wyjściowych może iterować do przodu przez sekwencję przy użyciu ++ operatora i może napisać element tylko raz przy użyciu * operatora .

  • Dane wejściowe. Iterator X wejściowy może iterować do przodu przez sekwencję przy użyciu ++ operatora i odczytywać element dowolną liczbę razy przy użyciu * operatora . Iteratory wejściowe można porównać przy użyciu == operatorów i != . Po inkrementacji dowolnej kopii iteratora wejściowego żadna z innych kopii nie może być bezpiecznie porównywana, wyłuszczone lub zwiększana później.

  • Dalej. IteratorX przesyłania dalej może iterować do przodu przez sekwencję przy użyciu operatora ++ i może odczytywać dowolny element lub zapisywać elementy inne niż const dowolną liczbę razy za pomocą * operatora . Dostęp do elementów członkowskich można uzyskać za pomocą -> operatora i porównać iteratory przesyłania dalej za pomocą == operatorów i != . Można utworzyć wiele kopii iteratora do przodu, z których każda może być wyłuszczone i zwiększana niezależnie. Iterator przesyłania dalej, który jest inicjowany bez odwołania do żadnego kontenera, jest nazywany iteratorem przekazywania o wartości null. Iteratory przesyłania dalej o wartości null zawsze są porównywane równe.

  • Dwukierunkowe. Iterator X dwukierunkowy może mieć miejsce iteratora do przodu. Można jednak również dekrementować iterator dwukierunkowy, jak w --Xpliku , X--lub (V = *X--). Możesz uzyskać dostęp do elementów członkowskich i porównać iteratory dwukierunkowe w taki sam sposób, jak iteratory przesyłania dalej.

  • Dostęp losowy. Iterator X dostępu losowego może mieć miejsce iteratora dwukierunkowego. Za pomocą iteratora dostępu losowego możesz użyć operatora [] indeksu dolnego, aby uzyskać dostęp do elementów. Można użyć +operatorów , -+= i-=, aby przejść do przodu lub do tyłu określoną liczbę elementów i obliczyć odległość między iteratorami. Można porównać iteratory dwukierunkowe przy użyciu ==poleceń , , !=, <>, , <=i >=.

Wszystkie iteratory można przypisać lub skopiować. Zakłada się, że są to lekkie obiekty i są często przekazywane i zwracane przez wartość, a nie przez odwołanie. Należy również pamiętać, że żadna z opisanych wcześniej operacji nie może zgłosić wyjątku podczas wykonywania na prawidłowym iteratorze.

Hierarchia kategorii iteratorów można podsumować, wyświetlając trzy sekwencje. W przypadku dostępu tylko do zapisu do sekwencji można użyć dowolnego z:

iterator danych wyjściowych
-> iterator do przodu
-> iterator dwukierunkowy
-> iterator dostępu losowego

Strzałka w prawo oznacza, że "można zamienić na". Każdy algorytm, który wywołuje iterator danych wyjściowych, powinien działać ładnie z iteratorem do przodu, na przykład, ale nie w drugą stronę.

W przypadku dostępu tylko do odczytu do sekwencji można użyć dowolnego z:

iterator wejściowy
-> iterator do przodu
-> iterator dwukierunkowy
-> iterator dostępu losowego

Iterator danych wejściowych jest najsłabszy ze wszystkich kategorii, w tym przypadku.

Na koniec, aby uzyskać dostęp do odczytu/zapisu do sekwencji, można użyć dowolnego z:

iterator przesyłania dalej
-> iterator dwukierunkowy
-> iterator dostępu losowego

Wskaźnik obiektu może zawsze służyć jako iterator dostępu losowego, dzięki czemu może służyć jako dowolna kategoria iteratora, jeśli obsługuje odpowiedni dostęp do odczytu/zapisu do wyznaczonej sekwencji.

Iterator Iterator inny niż wskaźnik obiektu musi również definiować typy składowe wymagane przez specjalizację iterator_traits<Iterator>. Te wymagania można spełnić, Iterator korzystając z iteratora klasy bazowej publicznej.

Ważne jest, aby zrozumieć obietnice i ograniczenia każdej kategorii iteratora, aby zobaczyć, jak iteratory są używane przez kontenery i algorytmy w standardowej bibliotece języka C++.

Uwaga

Można unikać jawnego używania iteratorów przy użyciu pętli range-for. Aby uzyskać więcej informacji, zobacz Range-based for statement (Zakres oparty na instrukcji).

Program Microsoft C++ oferuje teraz sprawdzone iteratory i iteratory debugowania, aby upewnić się, że nie zastąpisz granic kontenera. Aby uzyskać więcej informacji, zobacz Sprawdzone iteratory i Obsługa iteratora debugowania.

Zobacz też

Dokumentacja standardowej biblioteki C++
Bezpieczeństwo wątku w standardowej bibliotece C++