Lecții din modul (2/2)
Referințe și împrumuturi
În Rust, trecerea dreptului de proprietate înainte și înapoi către funcții poate fi plictisitoare. Pentru a rezolva acest lucru, Rust folosește referințe (&).
Crearea unei referințe la o valoare se numește Împrumut.
Referințe imuabile
O referință este declarată prin prefixarea tipului sau a variabilei cu simbolul &. În mod implicit, referințele sunt imuabile: permit citirea valorii, dar nu modificarea acesteia.
fn main() {
let s1 = String::from("hello");
// We pass a reference to s1, not ownership
let len = calculate_length(&s1);
// s1 is still usable here!
println!("The length of '{}' is {}.", s1, len);
}
fn calculate_length(s: &String) -> usize { // s is a reference to a String
s.len()
} // Here, s goes out of scope, but since it doesn't own the value, nothing happensReferințe mutabile
Dacă trebuie să modificați o valoare împrumutată, trebuie să utilizați o referință modificabilă cu &mut. Variabila originală trebuie, de asemenea, declarată mutabilă cu mut:
fn main() {
let mut s = String::from("hello");
// We pass a mutable reference
change(&mut s);
println!("{}", s); // Prints "hello, world"
}
fn change(some_string: &mut String) {
some_string.push_str(", world");
}Regulile de împrumut
Pentru a preveni coruperea memoriei și cursele de date în timpul compilării, Rust aplică două reguli fundamentale:
- Puteți avea orice număr de referințe imuabile (
&T) la o valoare în același timp. - SAU puteți avea exact o referință mutabilă (
&mut T) la o valoare odată.
Nu puteți combina referințe imuabile și mutabile pentru aceeași valoare în același domeniu:
let mut s = String::from("hello");
let r1 = &s; // Valid
let r2 = &s; // Valid
// let r3 = &mut s; // COMPILATION ERROR! You cannot create &mut s if s is already borrowed as immutableDomeniul de aplicare și duratele de viață non-lexicale (NLL)
Din punct de vedere istoric, sfera unei referințe a durat până la sfârșitul blocului în care a fost creată. Astăzi, compilatorul lui Rust este mai inteligent datorită Non-Lexical Lifetimes (NLL): domeniul de aplicare al unei referințe se termină la ultima linie în care este de fapt folosită, nu neapărat la sfârșitul blocului.
Acest lucru face ca următorul cod să fie perfect valabil:
let mut s = String::from("hello");
let r1 = &s;
let r2 = &s;
println!("{} and {}", r1, r2); // Last use of r1 and r2. The immutable references expire here!
let r3 = &mut s; // Valid! No active immutable references exist at this pointÎncercați-l singur
Transmite o referință imuabilă a lui s1 la funcția calculate_length folosind simbolul &.
Afișează indiciu
Înlocuiți `/* TODO \_/`cu`&s1` pentru a transmite o referință imuabilă la șir.
Soluție disponibilă după 3 încercări
Faceți variabila s mutabilă (let mut s) și transmiteți o referință mutabilă (&mut s) la funcția de modificare pentru a-i permite să modifice șirul.
Afișează indiciu
Folosiți `let mut s`in loc de`let s`and call`change(&mut s);`.
Soluție disponibilă după 3 încercări
Declare a variable s containing String::from("Rust"). Create two distinct immutable references r1 and r2 to s, and finally print both references separated by a space using the println! macro.
Afișează indiciu
Assign `let r1 = &s;` and `let r2 = &s;` to obtain two immutable references, then print them with `println!("{} {}", r1, r2);`.
Soluție disponibilă după 3 încercări