Salt la conținutul principal
Modulul 3 · Lecția 2 din 26/14 în curs~15 min
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.

Rust
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 happens

Referinț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:

Rust
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:

  1. Puteți avea orice număr de referințe imuabile (&T) la o valoare în același timp.
  2. 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:

Rust
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 immutable

Domeniul 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:

Rust
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

Exercițiu#rust.m3.l2.e1
Încercări: 0Se încarcă…

Transmite o referință imuabilă a lui s1 la funcția calculate_length folosind simbolul &.

Se încarcă editorul...
Afișează indiciu

Înlocuiți `/* TODO \_/`cu`&s1` pentru a transmite o referință imuabilă la șir.

Soluție disponibilă după 3 încercări

Exercițiu#rust.m3.l2.e2
Încercări: 0Se încarcă…

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.

Se încarcă editorul...
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

Exercițiu#rust.m3.l2.e3
Încercări: 0Se încarcă…

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.

Se încarcă editorul...
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