Iterator Aufhebungs-Regeln
Was sind die iterator-Aufhebungs-Regeln für C++ Container?
Vorzugsweise in einer zusammenfassenden Liste format.
(Hinweis: Dies ist gedacht, um einen Eintrag zu Stack-Überlauf C++ FAQ. Wenn Sie möchten, dass die Kritik der Idee der Bereitstellung eines FAQ in dieser form, dann die Veröffentlichung auf meta, die begann, alle diese wäre der richtige Ort, das zu tun. Antworten auf diese Frage sind überwacht,C++ chatroom, wo die FAQ-Idee, begann in den ersten Platz, so dass Ihre Antwort wird sehr wahrscheinlich durch zu Lesen wer kam auf die Idee).
Sollten die Antworten werden im gleichen format wie Ihre Antwort?
IMO wäre das die bevorzugte Symmetrie aber ich kann mich nicht durchsetzen 😛
was ist mit c++20?
Existiert noch nicht 😉
IMO wäre das die bevorzugte Symmetrie aber ich kann mich nicht durchsetzen 😛
was ist mit c++20?
Existiert noch nicht 😉
InformationsquelleAutor Lightness Races in Orbit | 2011-06-22
Du musst angemeldet sein, um einen Kommentar abzugeben.
C++17 (Alle Referenzen sind aus der abschließenden Arbeitsentwurf CPP17 - n4659)
Einsetzen
Sequenz-Containern
vector
: Die Funktioneninsert
,emplace_back
,emplace
,push_back
Ursache Umverteilung, wenn die neue Größe größer ist als die alte Kapazität. Neuzuweisung ungültig werden alle Referenzen, Pointer und Iteratoren unter Bezugnahme auf die Elemente in der Sequenz. Wenn keine Umverteilunggeschieht, werden alle Iteratoren und Referenzen, bevor Sie die Einfügemarke bleiben gültig. [26.3.11.5/1]
Mit Bezug auf die
reserve
Funktion, Neuzuweisung ungültig werden alle Referenzen, Pointer und Iteratoren unter Bezugnahme auf die Elemente in der Sequenz. Keine Umverteilung erfolgt während Einfügungen passieren, dass nach einem Aufrufreserve()
bis zu der Zeit, wenn eine Einfügung machen würde, die Größe des Vektors größer ist als der Wert dercapacity()
. [26.3.11.3/6]deque
: Eine insertion in der Mitte der deque ungültig alle Iteratoren und Referenzen auf Elemente der deque. Eine Einfügung am Ende der deque ungültig alle Iteratoren auf die deque, hat aber keine Auswirkung auf die Gültigkeit von Referenzen auf Elemente der deque. [26.3.8.4/1]list
: Berührt das nicht die Gültigkeit von Iteratoren und Referenzen. Wenn eine exception geworfen wird, gibt es keine Wirkung. [26.3.10.4/1].Die
insert
,emplace_front
,emplace_back
,emplace
,push_front
,push_back
Funktionen sind unter diese Regel.forward_list
: Keiner der überlastung derinsert_after
soll hierdurch die Gültigkeit von Iteratoren und Referenzen [26.3.9.5/1]array
: Als Regel, Iteratoren zu einem array sind nie für ungültig erklärt während der gesamten Lebensdauer des Arrays. Sollte man jedoch beachten, dass während der swap, der iterator wird weiterhin auf das gleiche array-element, und somit seinen Wert ändern.Assoziative Container
All Associative Containers
: Dieinsert
undemplace
Mitglieder berührt nicht die Gültigkeit von Iteratoren und Referenzen auf container [26.2.6/9]Ungeordnete Assoziative Container
All Unordered Associative Containers
: Aufwärmen Iteratoren ungültig, änderungen der Bestellung zwischen den Elementen, und die Veränderungen, die Eimer Elemente angezeigt, aber nicht außer Kraft, die Zeiger oder Referenzen auf Elemente. [26.2.7/9]Die
insert
undemplace
Mitglieder berührt nicht die Gültigkeit der Referenzen auf container-Elemente, aber möglicherweise ungültig alle Iteratoren auf die container. [26.2.7/14]Die
insert
undemplace
Mitglieder berührt nicht die Gültigkeit von Iteratoren, wenn(N+n) <= z * B
, woN
ist die Anzahl der Elemente im container vor der insert-operation,n
ist die Anzahl der eingefügten Elemente,B
ist der container, die Eimer zu zählen, undz
ist der container die maximale Auslastung. [26.2.7/15]All Unordered Associative Containers
: Im Falle eines merge-Vorgangs (z.B.a.merge(a2)
), Iteratoren bezogen auf die übertragenen Elemente und alle Iteratoren bezogen aufa
für ungültig erklärt werden, aber Iteratoren auf Elemente noch ina2
gültig bleiben. (Tabelle 91 — Ungeordnete assoziative container)Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerLöschung
Sequenz-Containern
vector
: Die Funktionenerase
undpop_back
ungültig Iteratoren und Referenzen an oder nach dem Punkt, der auf "löschen". [26.3.11.5/3]deque
: Eine erase-Vorgang, löscht das Letzte element aus einemdeque
ungültig macht nur der past-the-end-iterator und alle Iteratoren und Verweise auf die gelöschten Elemente. Eine löschen-operation, löscht das erste element einesdeque
aber nicht das Letzte element ist ungültig nur Iteratoren und Verweise auf die gelöschten Elemente. Eine löschen-operation, löscht weder das erste element nicht das Letzte element einerdeque
erlischt die past-the-end-iterator und alle Iteratoren und Referenzen auf alle Elemente desdeque
.[ Hinweis:
pop_front
undpop_back
sind erase operations. —Ende Anmerkung ] [26.3.8.4/4]list
: Invalidiert werden nur die Iteratoren und Verweise auf die gelöschten Elemente. [26.3.10.4/3]. Dies gilt fürerase
,pop_front
,pop_back
,clear
Funktionen.remove
undremove_if
member-Funktionen: Löscht alle Elemente in der Liste nach, indem Sie eine Liste mit iteratori
für die die folgenden Bedingungen halten:*i == value
,pred(*i) != false
. Invalidiert werden nur die Iteratoren und Verweise auf die gelöschten Elemente [26.3.10.5/15].unique
member-Funktion - Löscht alle, aber das erste element von jeder aufeinanderfolgenden Gruppe von gleichen Elementen bezeichnet, die durch den iteratori
im Bereich[first + 1, last)
für die*i == *(i-1)
(für die version der einzigartigen, ohne Argumente) oderpred(*i, *(i - 1))
(für die version von unique mit einer Prädikat-argument) hält. Invalidiert werden nur die Iteratoren und Verweise auf die gelöschten Elemente. [26.3.10.5/19]forward_list
:erase_after
sind ungültig, nur Iteratoren und Verweise auf die gelöschten Elemente. [26.3.9.5/1].remove
undremove_if
member-Funktionen - Löscht alle Elemente in der Liste nach, indem Sie eine Liste mit iterator i, für die die folgenden Bedingungen halten:*i == value
(fürremove()
),pred(*i)
ist wahr (fürremove_if()
). Invalidiert werden nur die Iteratoren und Verweise auf die gelöschten Elemente. [26.3.9.6/12].unique
member-Funktion - Löscht alle, aber das erste element von jeder aufeinanderfolgenden Gruppe von gleichen Elemente bezeichnet, auf die der iterator i im Bereich [first + 1, last), für die*i == *(i-1)
(für die version ohne Argumente) oderpred(*i, *(i - 1))
(für die version mit einer Prädikat-argument) hält. Invalidiert werden nur die Iteratoren und Verweise auf die gelöschten Elemente. [26.3.9.6/16]All Sequence Containers
:clear
ungültig werden alle Referenzen, Pointer und Iteratoren unter Bezugnahme auf die Elemente von a und kann zum erlöschen der past-the-end-iterator (Tabelle 87 — Sequence-Anforderungen für container). Aber fürforward_list
,clear
hat nicht die Unwirksamkeit past-the-end-Iteratoren. [26.3.9.5/32]All Sequence Containers
:assign
ungültig werden alle Referenzen, Pointer undIteratoren Bezugnahme auf die Elemente des Containers. Für
vector
unddeque
auch kein past-the-end-iterator. (Tabelle 87 — Sequence-Anforderungen für container)Assoziative Container
All Associative Containers
: Dieerase
Mitglieder erlöschen nur Iteratoren und Verweise auf die gelöschten Elemente [26.2.6/9]All Associative Containers
: Dieextract
Mitglieder erlöschen nur Iteratoren auf das entfernte element; Zeiger und Referenzen auf entfernte element bleiben gültig [26.2.6/10]Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerAllgemeine Behälter-Anforderungen an iterator-Invalidierung:
Sofern nicht anders angegeben (entweder explizit oder indem Sie eine Funktion definieren, die in Bezug auf andere Funktionen), das aufrufen eines container-member-Funktion oder der übergabe der container als argument, um eine library-Funktion wird nicht ungültig Iteratoren an, oder ändern Sie die Werte der Objekte im container. [26.2.1/12]
kein
swap()
Funktion ungültig macht, keine Referenzen, Zeigern oder Iteratoren Bezugnahme auf die Elemente der Container getauscht. [ Hinweis: Der end() iterator bezieht sich nicht auf ein beliebiges element, so kann es für ungültig erklärt werden. —Ende Hinweis ] [26.2.1/(11.6)]Als Beispiele für die oben genannten Anforderungen:
transform
Algorithmus: Dieop
undbinary_op
Funktionen begründet nicht die Unwirksamkeit Iteratoren oder Teilbereiche oder ändern von Elementen in die Bereiche [28.6.4/1]accumulate
Algorithmus: Im Bereich [first, last],binary_op
weder ändern von Elementen noch die Iteratoren ungültig werden oder Teilbereiche [29.8.2/1]reduce
Algorithmus: binary_op weder Iteratoren ungültig oder Teilbereiche, noch ändern-Elemente im Bereich [first, last]. [29.8.3/5]und so weiter...
Habe versucht, es zu tun, wie pro Ihre ursprüngliche Antwort-format. 🙂
können wir auch eine Auflistung für
std::string
? Ich denke, es unterscheidet sich vonstd::vector
durch SSOAufgrund SSO
string
schlägt fehl, der zweite Allgemeine Anforderung, die oben aufgeführten. So habe ich es nicht. Habe auch versucht zu kleben, um das gleiche Muster der bisherigen FAQ Einträge.InformationsquelleAutor P.W
C++03 (Quelle: Iterator Aufhebungs-Regeln (C++03))
Einsetzen
Sequenz-Containern
vector
: alle Iteratoren und Referenzen vor dem Punkt einsetzen, sind davon nicht betroffen, es sei denn, der neue container-Größe größer ist als die bisherige Leistung (in dem Fall alle Iteratoren und Referenzen ungültig werden) [23.2.4.3/1]deque
: alle Iteratoren und Referenzen sind ungültig, es sei denn, die eingefügt Mitglied ist an einem Ende (vorne oder hinten) der deque (in dem Fall werden alle Iteratoren ungültig werden, aber Verweise auf Elemente sind davon nicht betroffen) [23.2.1.3/1]list
: alle Iteratoren und Referenzen unberührt [23.2.2.3/1]Assoziative Container
[multi]{set,map}
: alle Iteratoren und Referenzen unberührt [23.1.2/8]Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerLöschung
Sequenz-Containern
vector
: jeder iterator und das Referenz-auch nach dem löschen ist ungültig [23.2.4.3/3]deque
: alle Iteratoren und Referenzen sind ungültig, es sei denn, die gelöschten Mitglieder sind an einem Ende (vorne oder hinten) der deque (in dem Fall nur Iteratoren und Referenzen auf die gelöschte Mitglieder werden für ungültig erklärt) [23.2.1.3/4]list
: es werden nur die Iteratoren und Referenzen auf das gelöschte element ist ungültig [23.2.2.3/3]Assoziative Container
[multi]{set,map}
: nur Iteratoren und Verweise auf die gelöschten Elemente werden für ungültig erklärt [23.1.2/8]Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerGrößenänderung
vector
: nach einfügen/löschen [23.2.4.2/6]deque
: nach einfügen/löschen [23.2.1.2/1]list
: nach einfügen/löschen [23.2.2.2/1]Hinweis 1
Note 2
Es ist nicht klar, in C++2003, ob "Ende" - Iteratoren sind vorbehaltlich der oben genannten Regeln; Sie sollten davon ausgehen, dass, eh, dass Sie (wie dies der Fall in der Praxis).
Anmerkung 3
Die Regeln für die Ungültigkeitserklärung von Zeigern sind die sames wie die Regeln für die Ungültigkeitserklärung von Referenzen.
Wenn ich mich Recht erinnere, irgendwo die Spezifikation besagt, dass die Ende-iterator ist nicht ein iterator ", um Objekte in dem betreffenden container". Ich Frage mich, wie diese Garantien Aussehen für den Ende-iterator in jedem Fall?
Diese Antwort ist freilich nicht klar ist, wie ich nahm eine Abkürzung, aber die Absicht ist zu sagen, dass die Größenänderung ist einfügen/löschen, wie in, wenn eine Neuzuweisung erforderlich ist, kann man berücksichtigen, dass das gleiche wie löschen, dann neu einfügen alle betroffenen Elemente. Dieser Abschnitt der die Antwort könnte sicherlich verbessert werden.
Aber es funktioniert nicht; siehe die zitierten standard-text. Sieht aus wie gefixt wurde C++11, wenn. 🙂
deque speichert die Daten in nicht-zusammenhängenden Blöcken. Das einfügen an den Anfang oder das Ende belegen können, einen neuen block, aber es bewegt sich nie um Vorherige Elemente, also die Zeiger bleiben gültig. Aber die Regeln für die nächste/Vorherige element ändern, wenn ein neuer block zugewiesen, so Iteratoren ungültig werden.
InformationsquelleAutor Lightness Races in Orbit
C++11 (Quelle: Iterator Aufhebungs-Regeln (C++0x))
Einsetzen
Sequenz-Containern
vector
: alle Iteratoren und Referenzen vor dem Punkt einsetzen, sind davon nicht betroffen, es sei denn, der neue container-Größe größer ist als die bisherige Leistung (in dem Fall alle Iteratoren und Referenzen ungültig werden) [23.3.6.5/1]deque
: alle Iteratoren und Referenzen sind ungültig, es sei denn, die eingefügt Mitglied ist an einem Ende (vorne oder hinten) der deque (in dem Fall werden alle Iteratoren ungültig werden, aber Verweise auf Elemente sind davon nicht betroffen) [23.3.3.4/1]list
: alle Iteratoren und Referenzen unberührt [23.3.5.4/1]forward_list
: alle Iteratoren und Referenzen unberührt (gilt fürinsert_after
) [23.3.4.5/1]array
: (n/a)Assoziative Container
[multi]{set,map}
: alle Iteratoren und Referenzen unberührt [23.2.4/9]Unsortierte assoziative Container
unordered_[multi]{set,map}
: alle Iteratoren ungültig, wenn die Aufbereitung erfolgt, sondern verweist unberührt [23.2.5/8]. Aufwärmen nicht Auftritt, wenn die Einfügung nicht zu den container-Größe zu überschreitenz * B
woz
ist der maximale load-Faktor und dieB
die aktuelle Anzahl der buckets. [23.2.5/14]Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerLöschung
Sequenz-Containern
vector
: jeder iterator und das Referenz-oder nach dem löschen ist ungültig [23.3.6.5/3]deque
: beim löschen des letzten Elements ist ungültig nur Iteratoren und Verweise auf die gelöschten Elemente und die past-the-end-iterator, löschen das erste element ist ungültig nur Iteratoren und Verweise auf die gelöschten Elemente, löschen alle anderen Elemente ungültig alle Iteratoren und Verweise (einschließlich der past-the-end-iterator) [23.3.3.4/4]list
: es werden nur die Iteratoren und Referenzen auf das gelöschte element ist ungültig [23.3.5.4/3]forward_list
: es werden nur die Iteratoren und Referenzen auf das gelöschte element ist ungültig (gilt fürerase_after
) [23.3.4.5/1]array
: (n/a)Assoziative Container
[multi]{set,map}
: nur Iteratoren und Verweise auf die gelöschten Elemente werden für ungültig erklärt [23.2.4/9]Ungeordnete assoziative Container
unordered_[multi]{set,map}
: nur Iteratoren und Verweise auf die gelöschten Elemente werden für ungültig erklärt [23.2.5/13]Container Adapter
stack
: geerbt von den zugrunde liegenden containerqueue
: geerbt von den zugrunde liegenden containerpriority_queue
: geerbt von den zugrunde liegenden containerGrößenänderung
vector
: nach einfügen/löschen [23.3.6.5/12]deque
: nach einfügen/löschen [23.3.3.3/3]list
: nach einfügen/löschen [23.3.5.3/1]forward_list
: nach einfügen/löschen [23.3.4.5/25]array
: (n/a)Hinweis 1
Note 2
Anmerkung 3
Anderen als dem oben genannten VORBEHALT bezüglich
swap()
, es ist nicht klar, ob "Ende" - Iteratoren sind vorbehaltlich der oben aufgeführten pro-container-Regeln; Sie sollten davon ausgehen, dass, eh, dass Sie sind.Anmerkung 4
vector
und alle ungeordnete assoziative Container unterstützenreserve(n)
die garantiert, dass keine automatische Größenänderung auftreten wird, wenigstens solange, bis die Größe der container wächst aufn
. Vorsicht sollte genommen werden, mit ungeordnete assoziative Container, weil ein künftiger Vorschlag erlauben die Spezifikation einer minimalen load factor, die es erlauben würde, Aufbereitung erfolgeninsert
nach genugerase
Operationen reduzieren die container-Größe unter der Mindest -; die Garantie sollte als potenziell nichtig nach einererase
.swap()
, was die Regeln für die iterator-Gültigkeit auf kopieren/verschieben Belegung?Kopieren/verschieben Zuordnung von was?
Wie einfügen, löschen, ändern der Größe und swap, copy/move-Zuweisung sind auch member-Funktionen von std::vector, damit ich denke, Sie könnten die Regeln der iterator Gültigkeit auch für Sie.
Ich denke, dass ich einen Fehler gemacht, weil
std::basic_string
scheint nicht zu zählen ist ein container, und sicherlich nicht nur ein container, in dem Abschnitt der Norm darstellt, der Hinweis gilt. Noch, wo steht denn SSO ist, ist verboten (ich weiß, die KUH ist)?Sind diese Regeln alle das gleiche in C++14? C++17 (so weit wie jetzt bekannt ist)?
InformationsquelleAutor Lightness Races in Orbit
Lohnt es sich wahrscheinlich hinzufügen, dass ein insert-iterator jeglicher Art (
std::back_insert_iterator
,std::front_insert_iterator
,std::insert_iterator
) garantiert ist, bleiben so lange gültig, wie alle Einfügungen erfolgt durch das iterator-und keine andere unabhängige iterator-ungültig-Ereignis Auftritt.Zum Beispiel, wenn Sie die Durchführung einer Reihe von Einfüge-Operationen in eine
std::vector
mithilfestd::insert_iterator
es ist durchaus möglich, dass diese Einfügungen-trigger-Vektor reallokation, die werden ungültig alle Iteratoren, die "Punkt" in der Richtung. Doch, der insert-iterator Frage ist, garantiert bleiben gültig, d.h. Sie können sicher fortsetzen der Sequenz von Einfügungen. Es gibt keine Notwendigkeit, über sorgen auslösen Vektor reallokation überhaupt.Dies wiederum gilt nur für Einfügungen durch die insert-iterator selbst. Wenn iterator-ungültig-Ereignis wird ausgelöst, indem Sie einige unabhängige Aktion auf den container, dann wird der insert-iterator wird ebenfalls für ungültig erklärt, in übereinstimmung mit den Allgemeinen Regeln.
Zum Beispiel, dieser code
ist garantiert, um durchzuführen eine gültige Sequenz von Insertionen in den Vektor, auch wenn der Vektor "entscheidet" neu zuzuteilen, irgendwo in der Mitte dieses Prozesses. Iterator
it
wird natürlich ungültig, aberit_ins
bleiben weiterhin gültig.InformationsquelleAutor AnT
Da diese Frage zieht so viele Stimmen und Art wird ein FAQ, ich denke, es wäre besser zu schreiben, eine separate Antwort zu schweigen von einem signifikanten Unterschied zwischen C++03 und C++11 in Bezug auf die Auswirkungen von
std::vector
's einfügen-operation auf die Gültigkeit von Iteratoren und Referenzen mit Bezug aufreserve()
undcapacity()
, die die meisten von Ihnen positiv bewertet werden Antwort übersehen.C++ 03:
C++11:
So, in C++03, es ist nicht "
unless the new container size is greater than the previous capacity (in which case all iterators and references are invalidated)
" wie bereits in der anderen Antwort, stattdessen sollte es "greater than the size specified in the most recent call to reserve()
". Das ist eine Sache, C++03 unterscheidet sich von C++11. In C++03, sobald eininsert()
bewirkt, dass die Größe des Vektors zu erreichen, wird der angegebene Wert in der vorherigenreserve()
nennen (die auch kleiner als die aktuellecapacity()
da einreserve()
könnte die Folge eine größerecapacity()
als gefragt), alle nachfolgendeninsert()
verursachen könnte, Umverteilung und ungültig alle Iteratoren und Referenzen. In C++11, das wird nicht passieren, und Sie können immer darauf Vertrauencapacity()
mit Sicherheit zu wissen, dass die nächste Umschichtung wird nicht stattfinden, bevor die Größe überführungencapacity()
.Abschließend, wenn Sie mit einem C++ - 03 Vektor-und Sie wollen sicherstellen, dass eine Umverteilung nicht passieren, wenn Sie ausführen, einführen, es ist der Wert des Arguments, die Sie zuvor übergeben
reserve()
, sollten Sie überprüfen Sie die Größe vor, nicht den Rückgabewert von einem Aufrufcapacity()
, sonst können Sie sich selbst überrascht über ein "vorzeitige" Umverteilung.Ich habe nicht "nicht bemerken"; es war ein redaktioneller Fehler, der in C++03, das war korrigiert in C++11. Keine mainstream-compiler nutzt den Fehler.
Ich denke, dass gcc schon ungültig Iteratoren in solchen Situationen.
InformationsquelleAutor neverhoodboy