Auf der Oberfläche sieht es aus wie drain
und into_iter
liefern ähnliche Iteratoren, nämlich über die Werte der Sammlung. Sie sind jedoch anders:
drain
nimmt eine &mut
zur Sammlung und die Sammlung ist danach verfügbar. into_iter
verbraucht die Sammlung. Was sind die geeigneten Verwendungen für jeden Iterator?
Sie sind etwas redundant miteinander. Wie Sie jedoch sagen, Drain
borgt gerade den Vektor, insbesondere hat er eine Lebensdauer, die mit dem Vektor verbunden ist. Wenn man einen Iterator zurückgeben möchte oder Iteratoren auf die flexibelste Art und Weise munge, ist die Verwendung von into_iter
besser, da es nicht an den Besitzer der ursprünglichen Vec
angekettet ist. Wenn man die Datenstruktur wiederverwenden möchte (z. B. die Zuweisung wiederverwenden), ist drain
der direkteste Weg, dies zu tun.
Ein (etwas) theoretisches Problem ist auch, dass Drain
benötigt, damit die ursprüngliche Struktur eine gültige Instanz von welchem Typ auch immer ist, dh entweder Invarianten erhält oder korrigiert oben am Ende, während IntoIter
die Struktur so viel wie es mag, Mangle, da es die vollständige Kontrolle über den Wert hat.
Ich sage nur "etwas" theoretisch, denn es gibt ein kleines Beispiel aus der realen Welt in std
bereits: HashMap
macht .drain
und .into_iter
über seinen internen RawTable
-Typ verfügbar, der auch diese hat Methoden. into_iter
kann einfach den Hash des Wertes lesen direkt verschoben und das ist das, aber drain
muss vorsichtig sein um den Hash zu aktualisieren, um anzuzeigen, dass die Zelle dann leer ist , nicht nur gelesen. Offensichtlich ist dies in diesem Fall absolut winzig (wahrscheinlich nur ein oder zwei zusätzliche Anweisungen), aber für kompliziertere Datenstrukturen wie Bäume können einige nicht-triviale Vorteile bestehen, wenn man die Invarianten der Datenstruktur bricht.
Nach der Verwendung von drain
ist Vec
leer, aber der Speicher, der zuvor für seine Elemente reserviert wurde, bleibt zugewiesen. Das bedeutet, dass Sie neue Elemente in Vec
einfügen können, ohne dass Sie Speicherplatz für sie reservieren müssen, bis Sie Vec
erreichen. Kapazität .
Beachten Sie, dass Sie alle Verweise auf löschen müssen, bevor Sie Vec
erneut verwenden können Drain
Iterator. Drain
's Implementierung von Drop
entfernt alle Elemente, die noch nicht aus Vec
entfernt wurden, daher ist Vec
leer, auch wenn Sie die Iteration nicht beendet haben.