2016-03-31 4 views
10

Trotz der Dokumentation gründlich zu lesen, bin ich ziemlich verwirrt über die Bedeutung des & und * Symbol in Rust, und ganz allgemein über das, was ist ein Rust Referenz genau.Bedeutung der Et-Zeichen ‚&‘ und Stern ‚*‘ Symbole in Rust

In diesem Beispiel scheint es, ähnlich wie bei einer C++ Referenz zu sein (das heißt, eine Adresse, die automatisch dereferenziert wird, wenn verwendet):

fn main() { 
    let c: i32 = 5; 
    let rc = &c; 
    let next = rc + 1; 
    println!("{}", next); // 6 
} 

jedoch der folgende Code funktioniert genau gleich:

Mit * zur Dereferenzierung wäre eine Referenz in C++ nicht korrekt. Also würde ich gerne verstehen, warum das in Rust stimmt.

Mein Verständnis so weit ist, dass das Einfügen * vor einem Dereferenzierungen Rust Referenz, aber die * implizit sowieso eingefügt, so dass Sie es nicht hinzufügen müssen (während in C++, es implizit eingefügt wird und wenn Sie fügen Sie es ein, Sie erhalten einen Kompilierungsfehler).

jedoch so etwas wie dies lässt sich nicht kompilieren:

fn main() { 
    let mut c: i32 = 5; 
    let mut next: i32 = 0; 
    { 
     let rc = &mut c; 
     next = rc + 1; 
    } 
    println!("{}", next); 
} 
<anon>:6:16: 6:18 error: binary operation `+` cannot be applied to type `&mut i32` [E0369] 
<anon>:6   next = rc + 1; 
         ^~ 
<anon>:6:16: 6:18 help: see the detailed explanation for E0369 
<anon>:6:16: 6:18 note: an implementation of `std::ops::Add` might be missing for `&mut i32` 
<anon>:6   next = rc + 1; 

Aber das funktioniert:

fn main() { 
    let mut c: i32 = 5; 
    let mut next: i32 = 0; 
    { 
     let rc = &mut c; 
     next = *rc + 1; 
    } 
    println!("{}", next); // 6 
} 

Es scheint, dass implizite dereferenzierenden (a la C++) für unveränderliche Referenzen korrekt ist , aber nicht für veränderbare Referenzen. Warum ist das?

Antwort

12

Die Verwendung von * zur Dereferenzierung einer Referenz wäre in C++ nicht korrekt. Also würde ich gerne verstehen, warum das in Rust stimmt.

Eine Referenz in C++ ist nicht identisch mit einer Referenz in Rust. Die Referenzen von Rust sind viel näher (in der Verwendung, nicht in der Semantik) zu den Zeigern von C++. In Bezug auf die Speicherdarstellung sind die Referenzen von Rust oft nur ein einziger Zeiger, während die Referenzen von C++ alternative Namen desselben Objekts sein sollen (und daher keine Speicherrepräsentation haben).

Der Unterschied zwischen C++ - Zeigern und Rust-Referenzen ist, dass die Referenzen von Rust nie NULL sind, niemals uninitialisiert und niemals hängend.

  • &i32 + i32
  • i32 + &i32
  • &i32:


    Das ist Add trait (siehe den unteren Teil des doc Seite) für die folgenden Paare und alle anderen numerischen Primitiven implementiert + &i32

Dies ist nur eine Annehmlichkeit, die die Entwickler von std-lib implementiert haben. Der Compiler kann herausfinden, dass ein &mut i32 verwendet werden kann, wo immer ein &i32 verwendet werden kann, aber das funktioniert nicht (noch?) Für Generika, so dass die std-lib-Entwickler müssten auch die Add Züge für die folgenden Kombinationen (und die für alle Primitiven implementieren):

  • &mut i32 + i32
  • i32 + &mut i32
  • &mut i32 + &mut i32
  • &mut i32 + &i32
  • &i32 + &mut i32

Wie Sie sehen können, kann das ziemlich außer Kontrolle geraten. Ich bin mir sicher, dass das in Zukunft weggehen wird. Bis dahin, beachten Sie, dass es eher selten ist, mit einem &mut i32 zu enden und zu versuchen, es in einem mathematischen Ausdruck zu verwenden.

+1

Danke, ich verstehe jetzt. Eigentlich hatte ich gedacht, es könnte so etwas sein, aber ich hatte den Gedanken verworfen, weil ich dachte, es wäre sehr seltsam, die Summe einer Ganzzahl mit einer solchen Ganzzahl zu definieren. Vielleicht sollte in dem Dokument betont werden, dass Rust-Referenzen als Adressen gedacht sind und nicht mit C++ - Referenzen zu verwechseln sind. Nochmals vielen Dank für die ausführliche Erklärung. –

3

Aus der Dokumentation für std::ops::Add:

impl<'a, 'b> Add<&'a i32> for &'b i32 
impl<'a> Add<&'a i32> for i32 
impl<'a> Add<i32> for &'a i32 
impl Add<i32> for i32 

Es scheint, die binäre Operator + für Zahlen für Kombinationen von gemeinsamen (aber nicht änderbaren) Referenzen der Operanden und im Besitz Versionen der Operanden durchgeführt wird. Es hat nichts mit automatischer Dereferenzierung zu tun.