Zasady unieważniania iteratora

Jakie są zasady unieważniania iteratorów dla kontenerów C++?

Najlepiej w formacie listy podsumowującej.

(uwaga: jest to wpis do Stack Overflow ' S C++ FAQ . Jeśli chcesz krytykować pomysł dostarczenia FAQ w tej formie, to post na meta, który rozpoczął to wszystko , byłby miejscem, aby to zrobić. Odpowiedzi na to pytanie są monitorowane w C++ chatroom , gdzie pomysł FAQ zaczął się w pierwszej kolejności, więc twój odpowiedź jest bardzo prawdopodobne, aby przeczytać przez tych, którzy wpadli na pomysł.)

Author: Community, 2011-06-22

4 answers

C++03 (Źródło: Iterator Unieważnia Reguły (C++03))


Wstawianie

kontenery sekwencyjne

  • vector: nie ma to wpływu na wszystkie Iteratory i odniesienia przed punktem wstawiania, chyba że nowy Rozmiar kontenera jest większy niż poprzednia pojemność (w tym przypadku wszystkie Iteratory i odniesienia są unieważnione) [23.2.4.3 / 1]
  • deque: Wszystkie Iteratory i odwołania są unieważnione, chyba że wstawiony element jest na końcu (z przodu lub z tyłu) deque (w którym to przypadku wszystkie Iteratory są unieważnione, ale odniesienia do elementów nie mają wpływu) [23.2.1.3/1]
  • list: wszystkie Iteratory i odwołania nie mają wpływu [23.2.2.3 / 1]

kontenery asocjacyjne

  • [multi]{set,map}: wszystkie Iteratory i odwołania nie mają wpływu [23.1.2 / 8]

Adaptery pojemników

  • stack: dziedziczony z bazowego kontenera
  • queue: kontener bazowy
  • priority_queue: dziedziczony z bazowego kontenera

Kasowanie

kontenery sekwencyjne

  • vector: każdy iterator i Referencja po punkcie Kasowania są unieważniane [23.2.4.3 / 3]
  • deque: Wszystkie Iteratory i odwołania są unieważniane, chyba że usunięte elementy są na końcu (z przodu lub z tyłu) deque (w tym przypadku unieważniane są tylko Iteratory i odniesienia do usuniętych elementów) [23.2.1.3/4]
  • list: unieważniane są tylko Iteratory i odwołania do usuniętego elementu [23.2.2.3 / 3]

kontenery asocjacyjne

  • [multi]{set,map}: unieważniane są tylko Iteratory i odwołania do usuniętych elementów [23.1.2 / 8]

Adaptery pojemników

  • stack: dziedziczony z bazowego kontenera
  • queue: dziedziczony z bazowego kontenera
  • priority_queue: Pojemnik

Zmiana rozmiaru

  • vector: zgodnie z insert/erase [23.2.4.2 / 6]
  • deque: zgodnie z insert/erase [23.2.1.2 / 1]
  • list: zgodnie z insert/erase [23.2.2.2/1]

Uwaga 1

O ile nie zaznaczono inaczej (albo jawnie lub definiując funkcję w zakresie innych funkcji), wywołując funkcja członka kontenera lub przekazywanie kontener jako argument a funkcja biblioteki nie unieważnia Iteratory do, lub zmienić wartości, obiektów wewnątrz tego kontenera. [23.1/11]

Uwaga 2

W C++2003 nie jest jasne, czy Iteratory "end" podlegają powyższym regułom ; w każdym razie należy założyć, że tak jest (jak to ma miejsce w praktyce).

Uwaga 3

Zasady unieważniania wskaźników są sames jako zasady unieważniania odniesień.

 383
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:37

C++11 (Source: iterator (C++0x))


Wstawianie

kontenery sekwencyjne

  • vector: nie ma to wpływu na wszystkie Iteratory i odniesienia przed punktem wstawiania, chyba że nowy Rozmiar kontenera jest większy niż poprzednia pojemność (w tym przypadku wszystkie Iteratory i odniesienia są unieważnione) [23.3.6.5 / 1]
  • deque: Wszystkie Iteratory i odwołania są unieważnione, chyba że wstawiony element jest na końcu (z przodu lub z tyłu) deque (w którym to przypadku wszystkie Iteratory są unieważnione, ale odniesienia do elementów nie mają wpływu) [23.3.3.4/1]
  • list: wszystkie Iteratory i odwołania nie mają wpływu [23.3.5.4 / 1]
  • forward_list: wszystkie Iteratory i odwołania bez wpływu (dotyczy insert_after) [23.3.4.5/1]
  • array: (n / a)

kontenery asocjacyjne

  • [multi]{set,map}: Wszystkie Iteratory i odwołania pozostają nienaruszone [23.2.4/9]

kontenery asocjacyjne niesortowane

  • unordered_[multi]{set,map}: wszystkie Iteratory unieważnione podczas ponownego rozmycia, ale odwołania nie mają wpływu [23.2.5 / 8]. Ponowne płukanie nie występuje, jeśli Wkładanie nie powoduje, że rozmiar pojemnika przekracza z * B, gdzie z jest maksymalnym współczynnikiem obciążenia i B bieżącą liczbą łyżek. [23.2.5/14]

Adaptery pojemników

  • stack: Pojemnik
  • queue: dziedziczony z podstawowego kontenera
  • priority_queue: dziedziczony z podstawowego kontenera

Kasowanie

kontenery sekwencyjne

  • [23.3.6.5/3]: każdy iterator i Referencja w punkcie kasowania lub po nim są unieważniane [23.3.6.5 / 3]
  • deque: wymazanie ostatniego elementu unieważnia tylko Iteratory i odwołania do usuniętych elementów oraz iteratora zakończonego; wymazanie pierwszego elementu unieważnia tylko Iteratory i odniesienia do usuniętych elementów; wymazanie wszelkich innych elementów unieważnia wszystkie Iteratory i odniesienia (w tym Iteratory przeszłe i końcowe) [23.3.3.4/4]
  • list: unieważniane są tylko Iteratory i odwołania do usuniętego elementu [23.3.5.4 / 3]
  • forward_list: unieważniane są tylko Iteratory i odwołania do usuniętego elementu (dotyczy erase_after) [23.3.4.5/1]
  • array: (n / a)

asocjacyjny pojemniki

  • [multi]{set,map}: unieważniane są tylko Iteratory i odwołania do usuniętych elementów [23.2.4 / 9]

niestandardowe pojemniki asocjacyjne

  • unordered_[multi]{set,map}: unieważniane są tylko Iteratory i odwołania do usuniętych elementów [23.2.5 / 13]

Adaptery pojemników

  • stack: dziedziczony z podstawowego kontenera
  • queue: dziedziczony z podstawowego kontenera
  • priority_queue: dziedziczenie z bazowego kontenera

Zmiana rozmiaru

  • vector: jak na insert/erase [23.3.6.5 / 12]
  • deque: zgodnie z insert/erase [23.3.3.3 / 3]
  • list: zgodnie z insert/erase [23.3.5.3 / 1]
  • forward_list: zgodnie z insert/erase [23.3.4.5 / 25]
  • array: (n / a)

Uwaga 1

O ile nie zaznaczono inaczej (albo jawnie lub definiując funkcję w zakresie innych funkcji), wywoływanie funkcja członka kontenera lub przekazywanie kontener jako argument a funkcja biblioteki nie unieważnia Iteratory do, lub zmienić wartości, obiektów wewnątrz tego kontenera. [23.2.1/11]

Uwaga 2

Brak funkcji swap () unieważnia wszelkie odniesienia, wskaźniki lub Iteratory nawiązując do elementów kontenery są wymieniane. [Note: The end () iterator nie odnosi się do żadnego element, więc to może zostać unieważnione . - Uwaga końcowa] [23.2.1/10]

Uwaga 3

Inne niż powyższe zastrzeżenie dotyczące swap(), nie jest jasne, czy Iteratory "końcowe" podlegają wyżej wymienionym regułom per-container ; w każdym razie powinieneś założyć, że tak.

Uwaga 4

vector i wszystkienieuporządkowane kontenery asocjacyjne wspierają reserve(n), co gwarantuje, że nie nastąpi automatyczna zmiana rozmiaru przynajmniej do rozmiaru Pojemnik rośnie do n. Należy zachować ostrożność w przypadku kontenerów asocjacyjnych nieuporządkowanych , ponieważ przyszły wniosek pozwoli na określenie minimalnego współczynnika obciążenia, co umożliwi ponowne załadowanie na insert po wystarczającej ilości operacji erase zmniejszy rozmiar kontenera poniżej minimum; gwarancję należy uznać za potencjalnie nieważną po erase.

 323
Author: Lightness Races in Orbit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 10:31:12

Warto chyba dodać, że iterator insert dowolnego rodzaju (std::back_insert_iterator, std::front_insert_iterator, std::insert_iterator) jest gwarantowane, że pozostanie ważne tak długo, jak wszystkie wstawki są wykonywane przez ten iterator i nie wystąpi żadne inne zdarzenie unieważniające iterator.

Na przykład, gdy wykonujesz serię operacji wstawiania do std::vector za pomocą std::insert_iterator jest całkiem możliwe, że wektor doświadczy zdarzenia realokacji, które unieważni wszystkie Iteratory, które "wskazują" na ten wektor. Jednak insert iterator, o którym mowa, ma gwarancję, że pozostanie ważny, tzn. można bezpiecznie kontynuować sekwencję wstawek. Nie ma potrzeby martwić się o wyzwalanie realokacji wektorów.

Odnosi się to ponownie tylko do wstawiania wykonywanego przez iterator insert. Jeśli iterator-unieważnienie zdarzenia zostanie wywołane przez jakieś niezależne działanie na kontenerze, wtedy iterator insert również zostanie unieważniony zgodnie z ogólnymi zasadami.

Na przykład, to kod

std::vector<int> v(10);
std::vector<int>::iterator it = v.begin() + 5;
std::insert_iterator<std::vector<int> > it_ins(v, it);

for (unsigned n = 20; n > 0; --n)
  *it_ins++ = rand();

Gwarantuje wykonanie prawidłowej sekwencji wstawek do wektora, nawet jeśli wektor "zdecyduje" się ponownie przydzielić gdzieś w środku tego procesu.

 34
Author: AnT,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-23 18:54:43

Ponieważ to pytanie przyciąga tak wiele głosów i staje się FAQ, myślę, że lepiej byłoby napisać oddzielną odpowiedź, aby wspomnieć o jednej znaczącej różnicy między C++03 A C++11 w odniesieniu do wpływu operacji wstawiania std::vector na ważność iteratorów i odniesień w odniesieniu do reserve() i capacity(), których najbardziej upvoted odpowiedź nie zauważył.

C++ 03:

Realokacja unieważnia wszystkie odwołania, wskaźniki i Iteratory nawiązując do elementy w sekwencji. Gwarantujemy, że nie realokacja odbywa się podczas wstawek, które następują po wywołaniu do reserve () do czasu, gdy wstawianie spowoduje, że rozmiar wektor większy niż rozmiar podany w ostatnim wywołaniu do reserve () .

C++11:

Realokacja unieważnia wszystkie odwołania, wskaźniki i Iteratory odwołując się do elementów w sekwencji. Gwarantujemy, że nie realokacja odbywa się podczas wstawek, które zdarzają się po wywołaniu do reserve () do czasu, gdy wstawianie spowoduje, że rozmiar wektor większy niż wartość capacity () .

Więc w C++03 nie jest to "unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)", Jak wspomniano w drugiej odpowiedzi, zamiast tego powinno być " greater than the size specified in the most recent call to reserve()". Jest to jedna rzecz, którą C++03 różni się od C++11. W C++03 raz insert() powoduje, że rozmiar wektora osiąga wartość określoną w poprzednim wywołaniu reserve() (która może być mniejsza niż obecnie capacity() ponieważ reserve() może spowodować większe capacity() niż oczekiwano), każde następne insert() może spowodować realokację i unieważnić wszystkie Iteratory i odwołania. W C++11 tak się nie stanie i zawsze możesz zaufać capacity(), aby wiedzieć z pewnością, że następna realokacja nie odbędzie się przed rozmiarem capacity().

Podsumowując, jeśli pracujesz z wektorem C++03 i chcesz mieć pewność, że realokacja nie nastąpi podczas wstawiania, jest to wartość argument, który wcześniej przekazałeś reserve(), że powinieneś sprawdzić rozmiar, a nie wartość zwracaną wywołania capacity(), w przeciwnym razie możesz się zaskoczyć ponowną alokacją" przedwczesne ".

 18
Author: neverhoodboy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-08 11:59:45