2016-01-14 3 views
8

Ein einfaches Beispiel:Woher weiß der Rust-Compiler, ob ein Wert verschoben wurde oder nicht?

struct A; 

fn main() { 
    test(2); 
    test(1); 
} 

fn test(i: i32) { 
    println!("test"); 
    let a = A; 
    if i == 2 { 
     us(a); 
    } 
    println!("end"); 
} 

impl Drop for A { 
    fn drop(&mut self) { 
     println!("drop"); 
    } 
} 

#[allow(unused_variables)] 
fn us(a: A){ 
    println!("use"); 
} 

Wenn ich es laufen, der Ausgang ist:

test 
use 
drop 
end 
test 
end 
drop 

ich im test(2) Fall verstehen, a bei us(a) bewegt wird, so dass eine Ausgabe es ist „Test-Einsatz -Drop-Ende ".

In der test(1) ist die Ausgabe jedoch "test-end-drop", was bedeutet, dass der Compiler weiß, dass a nicht verschoben wurde.

Wenn us(a) aufgerufen wird, wird es nicht notwendig sein a in test(i) fallen zu lassen, wird es in us(a) fallen gelassen werden; und wenn us(a) nicht aufgerufen wird, muss a nach println!("end") fallen gelassen werden.

Da der Compiler nicht wissen kann, ob us(a) aufgerufen wird oder nicht, wie kann der Compiler wissen, ob a.drop() nach println!("end") aufgerufen werden soll oder nicht?

Antwort

9

Dies wird in den Rustnomicon erklärt:

Ab Rust 1.0 sind die Drop-Flags eigentlich nicht so heimlich in einem versteckten Bereich jeglicher Art gebunkert, den Tropfen implementiert.

Das ausgeblendete Feld gibt an, ob der aktuelle Wert gelöscht wurde oder nicht, und wenn nicht, dann ist dies der Fall. Daher ist dies zur Laufzeit bekannt und erfordert ein wenig Buchführung.


Mit Blick auf die Zukunft gibt es einen RFC zu remove these hidden fields.

Die Idee des RFC ist die verborgenen Felder zu ersetzen:

  1. Identifizierung bedingungslose Tropfen (die brauchen keine Laufzeitprüfung)
  2. Stash ein verstecktes Feld auf dem Stapel

    :, im Funktions-Rahmen, für diese Werte bedingt

Diese neue Strategie hat mehrere Vorteile gegenüber dem alten fallen gelassen wird

  • der Hauptvorteil ist, dass #[repr(C)] wird nun immer eine Darstellung entsprechend der eigenen C geben, selbst wenn die struct implementiert Drop
  • ein weiterer wichtiger Vorteil ist, Daten speichern (indem sie nicht die struct Größe aufblasen)
  • ein weiterer kleiner Vorteil ist eine mögliche geringfügige Geschwindigkeitsverstärkung aufgrund von unbedingten Abfällen und besserem Zwischenspeichern (von der Verringerung der Speichergröße)
Verwandte Themen