tl; dr: Ja, das Verschieben von a macht std::vector<T, A>die Iteratoren möglicherweise ungültig
Der häufigste Fall (mit vorhanden std::allocator) ist, dass keine Ungültigmachung stattfindet, es jedoch keine Garantie gibt und das Wechseln von Compilern oder sogar das nächste Compiler-Update dazu führen kann, dass sich Ihr Code falsch verhält, wenn Sie sich darauf verlassen, dass Ihre Implementierung die Iteratoren derzeit nicht ungültig macht.
Zuweisung bei Umzug :
Die Frage, ob std::vectorIteratoren nach der Verschiebungszuweisung tatsächlich gültig bleiben können, hängt mit der Allokatorerkennung der Vektorvorlage zusammen und hängt vom Allokatortyp (und möglicherweise den jeweiligen Instanzen davon) ab.
In jeder Implementierung, die ich gesehen habe, macht die Verschiebungszuweisung einer std::vector<T, std::allocator<T>>1 Iteratoren oder Zeiger nicht ungültig. Es gibt jedoch ein Problem, wenn es darum geht, dies zu nutzen, da der Standard einfach nicht garantieren kann, dass Iteratoren für eine Verschiebungszuweisung einer std::vectorInstanz im Allgemeinen gültig bleiben , da der Container Allokator-fähig ist.
Benutzerdefinierte Zuweiser haben möglicherweise den Status. Wenn sie sich bei der Zuweisung von Verschiebungen nicht ausbreiten und nicht gleich vergleichen, muss der Vektor Speicher für die verschobenen Elemente mithilfe seines eigenen Zuweisers zuweisen.
Lassen:
std::vector<T, A> a{};
std::vector<T, A> b;
b = std::move(a);
Nun wenn
std::allocator_traits<A>::propagate_on_container_move_assignment::value == false &&
std::allocator_traits<A>::is_always_equal::value == false &&( möglicherweise ab c ++ 17 )
a.get_allocator() != b.get_allocator()
Dann bwird neuer Speicher zugewiesen und Elemente von verschobena nacheinander in diesen Speicher , wodurch alle Iteratoren, Zeiger und Referenzen ungültig werden.
Der Grund ist, dass die Erfüllung der obigen Bedingung 1 die Zuordnung des Allokators bei Containerumzug verbietet. Daher müssen wir uns mit zwei verschiedenen Instanzen des Allokators befassen. Wenn diese beiden Allokatorobjekte jetzt weder immer gleich ( 2. ) noch tatsächlich gleich vergleichen, haben beide Allokatoren einen unterschiedlichen Status. Ein Allokator ist xmöglicherweise nicht in der Lage, den Speicher eines anderen Allokators ymit einem anderen Status freizugeben, und daher kann ein Container mit Allokator xnicht einfach Speicher von einem Container stehlen, der seinen Speicher über zugewiesen hat y.
Wenn sich der Allokator bei der Verschiebungszuweisung ausbreitet oder wenn beide Allokatoren gleich sind, wird eine Implementierung sehr wahrscheinlich nur beigene aDaten erstellen, da sie sicher sein kann, den Speicher ordnungsgemäß freizugeben.
1 :std::allocator_traits<std::allocator<T>>::propagate_on_container_move_assignmentundstd::allocator_traits<std::allocator<T>>::is_always_equalbeide sind typdefs fürstd::true_type(für alle nicht spezialisiertenstd::allocator).
On-Move-Bau :
std::vector<T, A> a{};
std::vector<T, A> b(std::move(a));
Der Verschiebungskonstruktor eines Allokator-fähigen Containers verschiebt seine Allokator-Instanz aus der Allokator-Instanz des Containers, aus dem der aktuelle Ausdruck verschoben wird. Auf diese Weise wird die ordnungsgemäße Freigabefähigkeit sichergestellt, und der Speicher kann (und wird) gestohlen werden, da die Bewegungskonstruktion (mit Ausnahme von std::array) eine konstante Komplexität aufweisen muss.
Hinweis: Es gibt noch keine Garantie dafür, dass Iteratoren auch für Verschiebungskonstruktionen gültig bleiben.
Beim Tausch :
Es ist einfach zu fordern, dass die Iteratoren von zwei Vektoren nach einem Swap gültig bleiben (jetzt nur auf den jeweiligen Swap-Container zeigen), da das Swapping nur dann ein definiertes Verhalten aufweist, wenn
std::allocator_traits<A>::propagate_on_container_swap::value == true ||
a.get_allocator() == b.get_allocator()
Wenn sich die Allokatoren beim Auslagern nicht ausbreiten und wenn sie nicht gleich sind, ist das Auslagern der Container in erster Linie ein undefiniertes Verhalten.
a_iterjetzt auf ein Element verwiesen wird,bnachdemaes verschoben wurde.