2016-06-15 12 views
4

Der Condvar docs zeigt ein Beispiel, das die folgenden Leistungen enthält:Wann sollte "&" auf beiden Seiten einer Zuweisung verwendet werden?

let pair = Arc::new((Mutex::new(false), Condvar::new())); 
// <snipped for brevity> 
let &(ref lock, ref cvar) = &*pair; 

Ich frage mich, was der Vorteil & auf beiden Seiten dieser Zuordnung zu einschließlich sein könnte. Mit anderen Worten, warum nicht einfach schreiben:

let (ref lock, ref cvar) = *pair; 

Beide Versionen kompilieren; Gibt es irgendeinen semantischen Unterschied? Und wenn nicht, gibt es einen Grund, die Syntax zu bevorzugen, die im Beispiel erscheint?

Im Allgemeinen, Ich bin immer noch kämpfen zu verstehen, wann/wo &* sollte idiomatisch in Rust Code erscheinen. Mein Instinkt besteht darin, diese Zeichenkombination als No-Op zu sehen (zu lesen), obwohl ich weiß, dass dies wegen Rusts Deref Semantik nicht der Fall ist.

+0

Lassen Sie mich hinzufügen, dass ich das Design Absicht zu verstehen/Denken hinter Deref Verhalten https://github.com/rust-lang/rfcs/blob/master/text/0241-deref-conversions.md am nützlichsten gefunden haben . – Bosh

Antwort

3

Die Verwendung von & in diesem Fall macht keinen Unterschied, weil die LHS ein destructuring pattern ist. Meiner Meinung nach sollte dieses Beispiel & nicht verwenden. Allerdings gibt es in anderen Fällen ist ein wichtiger Unterschied: * den latenten Wert bewegt:

let p = *pair; // *Deref::deref(pair) 
// pair cannot be used anymore because the deferred value was moved 

let p = &*pair; // &*Deref::deref(pair) 
// p: &(Mutex::new(false), Condvar::new()) 
// p and pair can be used 

Ich kämpfe noch zu verstehen, wenn/wo & * idiomatisch in Rust Code erscheinen soll.

Im Allgemeinen &* verwenden, wenn ein Verweis auf den latenten Wert benötigt wird, wie in einem Funktionsaufruf:

fn sum(a: &u32, b: &u32) -> u32 { 
    a + b 
} 

fn main() { 
    let x = Box::new(10); 
    // println!("{:?}", sum(&1, x)); // do not work x is Box<u32> 
    // println!("{:?}", sum(&1, *x)); // do not work *x is u32 
    println!("{:?}", sum(&1, &*x)); // ok &*x is &u32 
} 

Mein Instinkt ist zu „sehen“ (lesen), um diese Zeichenkombination als ein No-Op, obwohl ich verstehe, dass dies wegen Rustens Deref-Semantik nicht der Fall ist.

Bedenkt man, dass The Book sagt „Deref zum Schreiben eigener Zeigertypen nützlich ist“, wie ich &* als „eine Bezugnahme auf den Wert, dass diese (smart) Zeiger auf“ lesen.

+0

Das ist großartig! Können Sie für '// * Deref :: deref (Paar) erklären, warum die' * '* und *' Deref' in Ihrer Erklärung erscheinen? Sollte nicht nur einer da sein? – Bosh

+0

Der Compiler übersetzt '* pair' in' * Deref :: deref (pair) 'und' & * pair' in '& * Deref :: deref (pair)', da "Deref :: deref" '& T' zurückgibt , dann erzeugt '* pair'' T' und '& * pair' erzeugt' & T'. – malbarbo

+0

Dumme Frage, aber wenn '* pair' zu' * Deref :: deref (pair) 'expandiert, warum erweitert sich das dann nicht zu' * Deref :: reference (* Deref :: deref (pair)) ' ? – Bosh

Verwandte Themen