2016-03-31 23 views
10

Nonostante la lettura completa della documentazione, sono piuttosto confuso sul significato del simbolo & e * in Rust e, più in generale, su ciò che è un riferimento di Rust Esattamente.Significato dei simboli "e" e "stella" * in Rust

In questo esempio, sembra essere simile a un riferimento C++ (cioè, un indirizzo che viene dereferenziato automaticamente se utilizzati):

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

Tuttavia, il seguente codice funziona esattamente lo stesso:

Utilizzare * per risolvere un riferimento non sarebbe corretto in C++. Quindi mi piacerebbe capire perché questo è corretto in Rust.

mia comprensione finora, è che, inserendo * di fronte a un riferimento dereferenziazioni Rust, ma il * è implicitamente inserito comunque in modo non c'è bisogno di aggiungere che (mentre in C++, è implicitamente inserito e se si inseriscilo si ottiene un errore di compilazione).

Tuttavia, una cosa del genere non può essere compilato:

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; 

Ma questo funziona:

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

Sembra che dereferenziazione implicita (a la C++) è corretta per i riferimenti immutabili , ma non per riferimenti mutevoli. Perchè è questo?

risposta

12

Utilizzando * per la dereferenziazione, un riferimento non sarebbe corretto in C++. Quindi mi piacerebbe capire perché questo è corretto in Rust.

Un riferimento in C++ non è lo stesso di un riferimento in Rust. I riferimenti di Rust sono molto più vicini (nell'uso, non in semantica) agli indicatori di C++. Per quanto riguarda la rappresentazione della memoria, i riferimenti di Rust sono spesso solo un singolo puntatore, mentre i riferimenti di C++ dovrebbero essere nomi alternativi dello stesso oggetto (e quindi non hanno alcuna rappresentazione di memoria).

La differenza tra puntatori C++ e riferimenti Rust è che i riferimenti di Rust non sono mai NULL, mai non inizializzati e mai pendenti.


La Add caratteristica è implementata (vedere la parte inferiore della pagina doc) per le seguenti coppie e tutti gli altri primitive numerici:

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

Questa è solo una cosa di convenienza implementata dagli sviluppatori di std-lib. Il compilatore può capire che un &mut i32 può essere utilizzato ovunque sia possibile usare un &i32, ma questo non funziona (ancora?) Per i medicinali generici, in modo che gli sviluppatori STD-lib avrebbe bisogno di implementare anche le Add tratti per le seguenti combinazioni (e quelli per tutte le primitive):

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

Come potete vedere, può diventare piuttosto fuori controllo. Sono sicuro che andrà via in futuro. Fino ad allora, si noti che è piuttosto raro trovare un &mut i32 e provare a usarlo in un'espressione matematica.

+1

Grazie, capisco ora. In realtà, avevo pensato che potesse essere qualcosa del genere ma avevo respinto il pensiero, pensando che sarebbe stato molto strano definire la somma di un intero con un indirizzo di un intero come quello. Forse dovrebbe essere sottolineato nel documento che i riferimenti di Rust devono essere pensati come indirizzi e non essere confusi con i riferimenti C++. Grazie ancora per la spiegazione dettagliata. –

3

Dalla documentazione per 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 

sembra che il binario operatore + per i numeri è implementato per le combinazioni di versioni condivise (ma non mutabili) riferimenti degli operandi e di proprietà degli operandi. Non ha nulla a che fare con il dereferenziamento automatico.

Problemi correlati