Shopping cart

0

Cart

  • 0 item

Nessun prodotto nel carrello.

All categories
 Corso Gratuito di Programmazione Rust Lezione 015 – References and Borrowing

SE VUOI PRENDERE LA CERTIFICAZIONE PER QUESTO CORSO CLICCA QUI

References and Borrowing

Il problema con il codice delle tuple nella Lista 4-5 è che dobbiamo restituire la String alla funzione chiamante in modo da poter ancora usare la String dopo la chiamata a calculate_length, perché la String è stata spostata in calculate_length. Invece, possiamo fornire un riferimento al valore della String. Un riferimento è simile a un puntatore nel senso che è un indirizzo che possiamo seguire per accedere ai dati memorizzati in quell’indirizzo; quei dati sono di proprietà di qualche altra variabile. A differenza di un puntatore, un riferimento è garantito di puntare a un valore valido di un particolare tipo per la vita di quel riferimento.

Ecco come definiresti e utilizzeresti una funzione calculate_length che ha un riferimento a un oggetto come parametro invece di prendere la proprietà del valore:

rust

fn main() {
let s1 = String::from("ciao");
let len = calculate_length(&s1); println!("La lunghezza di '{}' è {}.", s1, len);
}

fn calculate_length(s: &String) -> usize {
s.len()
}

Prima di tutto, notare che tutto il codice delle tuple nella dichiarazione della variabile e nel valore restituito della funzione è scomparso. In secondo luogo, notare che passiamo &s1 in calculate_length e, nella sua definizione, prendiamo &String invece di String. Questi simboli & rappresentano i riferimenti e ti consentono di fare riferimento a un valore senza prenderne la proprietà. Figura 4-5 rappresenta questo concetto.

Tre tabelle: la tabella per s contiene solo un puntatore alla tabella per s1. La tabella per s1 contiene i dati dello stack per s1 e punta ai dati di stringa nell’heap.

Nota: L’opposto del riferimento, usando &, è la dereferenziazione, che si ottiene con l’operatore di dereferenziazione, *. Vedremo alcuni utilizzi dell’operatore di dereferenziazione nel Capitolo 8 e discuteremo dettagli sulla dereferenziazione nel Capitolo 15.

Diamo un’occhiata più da vicino alla chiamata di funzione qui:

rust

let s1 = String::from("ciao");

let len = calculate_length(&s1);

La sintassi &s1 ci consente di creare un riferimento che si riferisce al valore di s1 ma non ne possiede la proprietà. Poiché non ne possiede la proprietà, il valore a cui punta non verrà eliminato quando il riferimento smette di essere utilizzato.

Allo stesso modo, la firma della funzione utilizza & per indicare che il tipo del parametro s è un riferimento. Aggiungiamo alcune annotazioni esplicative:

rust

fn calculate_length(s: &String) -> usize { // s è un riferimento a una String
s.len()
}

Il campo di applicazione in cui la variabile s è valida è lo stesso di qualsiasi parametro della funzione, ma il valore puntato dal riferimento non viene eliminato quando s smette di essere utilizzato, perché s non possiede la proprietà. Quando le funzioni hanno riferimenti come parametri invece dei valori effettivi, non avremo bisogno di restituire i valori per restituire la proprietà, perché non abbiamo mai avuto la proprietà.

Chiamiamo l’azione di creare un riferimento prestito. Come nella vita reale, se una persona possiede qualcosa, puoi prenderla in prestito da loro. Quando hai finito, devi restituirla. Non ne sei proprietario.

Allora, cosa succede se proviamo a modificare qualcosa che stiamo prendendo in prestito? Prova il codice nella Lista 4-6. Spoiler: non funziona!

rust

fn main() {
let s = String::from("ciao");
change(&s);
}

fn change(some_string: &String) {
some_string.push_str(", mondo");
}

Ecco l’errore:

javascript

$ cargo run
Compiling ownership v0.1.0 (file:///projects/ownership)
error[E0596]: cannot borrow `*some_string` as mutable, as it is behind a `&` reference
--> src/main.rs:8:5
|
7 | fn change(some_string: &String) {
| ------- help: consider changing this to be a mutable reference: `&mut String`
8 | some_string.push_str(", mondo");
| ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `some_string` is a `&` reference, so the data it refers to cannot be borrowed as mutable

For more information about this error, try `rustc --explain E0596`.
error: could not compile `ownership` due to previous error

Così come le variabili sono immutabili per impostazione predefinita, così lo sono anche i riferimenti. Non ci è consentito modificare qualcosa a cui abbiamo un riferimento.

1 Comment

Leave a Reply

Il tuo indirizzo email non sarà pubblicato. I campi obbligatori sono contrassegnati *