Wie kann ich eine Box wiederverwenden, aus der ich den Wert verschoben habe?

8

Ich habe einen nicht kopierbaren Typ und eine Funktion, die es verbraucht und (vielleicht) erzeugt:

%Vor%

Betrachten Sie nun einen Typ, der konzeptionell sehr ähnlich zu Box :

ist %Vor%

Wir können eine Funktion schreiben, die den Inhalt von NotBox vorübergehend ausschaltet und etwas zurückgibt, bevor wir es zurückgeben:

%Vor%

Ich möchte eine analoge Funktion schreiben, die mit Box es funktioniert, aber der Compiler mag es nicht:

%Vor%

Ich könnte stattdessen Some(Box::new(new_foo)) zurückgeben, aber das führt unnötige Zuweisung durch - ich habe bereits etwas Speicher zur Verfügung! Ist es möglich, das zu vermeiden?

Ich möchte auch die match -Anweisungen loswerden, aber der Compiler ist nicht zufrieden damit (sogar für die NotBox -Version):

%Vor%

Kann man das umgehen?

    
mrhania 15.07.2016, 13:17
quelle

3 Antworten

8

Es ist also ein Sonderfall, aus einem Box herauszukommen ... was nun?

Das Modul std::mem bietet eine Reihe sicherer Funktionen, um Werte zu verschieben, ohne Löcher (!) in die Speichersicherheit von Rust zu bohren. Von Interesse sind hier swap und replace :

%Vor%

Was wir so verwenden können:

%Vor%

Es hilft auch im Fall map , weil es nicht das Box ausborgt:

%Vor%     
Matthieu M. 15.07.2016, 16:24
quelle
4

Das Verschieben von Boxen wird im Compiler speziell behandelt. Du kannst etwas aus ihnen herausbewegen, aber du kannst etwas nicht zurückbewegen, weil der Akt des Auszugs auch die Zuordnung aufhebt. Sie können mit std::ptr::write , std::ptr::read und std::ptr::replace etwas albernes machen, aber es ist schwer, es richtig zu machen, weil etwas gültig in einem Box sein sollte, wenn es gelöscht wird. Ich würde empfehlen, nur die Zuweisung zu akzeptieren oder stattdessen zu einem Box<Option<Foo>> zu wechseln.

    
Thiez 15.07.2016 14:23
quelle
0
  

Wir können eine Funktion schreiben, die den Inhalt der NotBox vorübergehend ausschaltet und etwas zurückgibt, bevor wir sie zurückgeben.

Das liegt daran, dass Sie sich teilweise aus der Struktur herausbewegen können, die Sie als Wert annehmen. Es verhält sich so, als ob alle Felder separate Variablen wären. Das ist jedoch nicht möglich, wenn die Struktur Drop implementiert, weil drop die gesamte Struktur als gültig (immer im Falle von Panik) benötigt.

Um eine Problemumgehung zu bieten, haben Sie nicht genügend Informationen zur Verfügung gestellt - insbesondere warum baz Box als Argument verwenden muss und warum quux nicht? Welche Funktionen gehören Ihnen und welche sind Teil einer API, die Sie nicht ändern können? Was ist der wahre Typ von Foo ? Ist es groß?

Die beste Problemumgehung wäre, Box überhaupt nicht zu verwenden.

    
krdln 15.07.2016 14:32
quelle