Wann sollte ich 'drain' vs 'into_iter' verwenden?

9

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:

%Vor%

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?

    
Shepmaster 11.01.2015, 00:44
quelle

2 Antworten

9

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.

    
huon 11.01.2015, 01:01
quelle
7

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.

    
Francis Gagné 11.01.2015 01:02
quelle

Tags und Links