
Ronag
Wie kann ein umgezogener Container richtig wiederverwendet werden?
std::vector<int> container;
container.push_back(1);
auto container2 = std::move(container);
// ver1: Do nothing
//container2.clear(); // ver2: "Reset"
container = std::vector<int>() // ver3: Reinitialize
container.push_back(2);
assert(container.size() == 1 && container.front() == 2);
Nach dem, was ich im C++0x-Standardentwurf gelesen habe; ver3 scheint der richtige Weg zu sein, da ein Objekt nach move in a ist
“Sofern nicht anders angegeben, müssen solche ausgelagerten Objekte in einen gültigen, aber nicht spezifizierten Zustand versetzt werden.”
Ich habe noch nie einen Fall gefunden, in dem es “anders angegeben” ist.
Obwohl ich ver3 etwas umständlich finde und ver1 viel lieber gewesen wäre, kann vec3 zwar einige zusätzliche Optimierungen ermöglichen, aber andererseits leicht zu Fehlern führen.
Ist meine Vermutung richtig?
Aus Abschnitt 17.3.26 der Spezifikation “gültiger, aber nicht spezifizierter Zustand”:
ein Objektzustand, der nicht angegeben ist, außer dass die Invarianten des Objekts erfüllt sind und Operationen an dem Objekt sich wie für seinen Typ angegeben verhalten [ Example: If an object x
of type std::vector<int>
is in a valid but unspecified state, x.empty()
can be
called unconditionally, and x.front()
can be called only if x.empty()
returns false. —end example ]
Daher ist das Objekt aktiv. Sie können jeden Vorgang ausführen, der keine Vorbedingung erfordert (es sei denn, Sie überprüfen zuerst die Vorbedingung).
clear
hat zum Beispiel keine Vorbedingungen. Und es wird das Objekt in einen bekannten Zustand zurückversetzen. Also einfach löschen und wie gewohnt verwenden.

Grizzly
Das Objekt befindet sich in a gültiger, aber undefinierter Zustand bedeutet im Grunde, dass der genaue Zustand des Objekts zwar nicht garantiert, aber gültig ist und daher garantiert funktionieren, dass Member-Funktionen (oder Nicht-Member-Funktionen) funktionieren, solange sie sich nicht darauf verlassen, dass das Objekt einen bestimmten Zustand hat.
Die clear()
Die Member-Funktion hat keine Vorbedingungen für den Zustand des Objekts (außer natürlich, dass sie gültig ist) und kann daher für verschobene Objekte aufgerufen werden. Andererseits bspw front()
hängt davon ab, dass der Container nicht leer ist, und kann daher nicht aufgerufen werden, da nicht garantiert wird, dass er nicht leer ist.
Daher sollten sowohl ver2 als auch ver3 in Ordnung sein.

Ben Voigt
Ich glaube nicht, dass Sie irgendetwas mit einem verschobenen Objekt tun können (außer es zu zerstören).
Kannst du nicht verwenden swap
stattdessen alle Vorteile des Umzugs nutzen, aber den Container in einem bekannten Zustand belassen?
9647500cookie-checkEinen umgezogenen Container wiederverwenden?yes
Du könntest einfach anrufen
clear
da es keine Vorbedingungen hat (und daher nicht auf den Zustand des Objekts angewiesen ist).– Nicol Bolas
6. Februar 2012 um 23:26 Uhr
@Nicol: Nehmen wir an, es gab eine
std::vector
Implementierung, die einen Zeiger auf seine Größe gespeichert hat (scheint albern, aber legal). Wenn Sie sich von diesem Vektor wegbewegen, kann der Zeiger NULL bleiben, danachclear
würde versagen.operator=
könnte auch scheitern.– Ben Voigt
6. Februar 2012 um 23:27 Uhr
@Ben: Ich denke, das würde den “gültigen” Teil von “gültig, aber nicht spezifiziert” verletzen.
– Ildjarn
6. Februar 2012 um 23:29 Uhr
@ildjarn: Ich dachte, es bedeutet nur, dass es sicher ist, den Destruktor auszuführen.
– Ben Voigt
6. Februar 2012 um 23:36 Uhr
Ich denke, die Frage ist, was ist “gültig”?
– ronag
6. Februar 2012 um 23:38 Uhr