Direct naar de hoofdinhoud
Module 3 · Les 2 van 26/14 in de cursus~15 min
Modulelessen (2/2)

Referenties en lenen

In Rust kan het lastig zijn om eigendom heen en weer over te dragen aan functies. Om dit op te lossen gebruikt Rust referenties (&).

Het aanmaken van een verwijzing naar een waarde heet Lenen.

Onveranderlijke referenties

Een referentie wordt gedeclareerd door het type of de variabele vooraf te laten gaan door het symbool &. Standaard zijn referenties onveranderlijk: ze maken het lezen van de waarde mogelijk, maar kunnen deze niet wijzigen.

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

Veranderlijke referenties

Als u een geleende waarde moet wijzigen, moet u een veranderlijke referentie gebruiken met &mut. De originele variabele moet ook veranderlijk worden verklaard met 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");
}

De regels voor lenen

Om geheugenbeschadiging en dataraces tijdens het compileren te voorkomen, handhaaft Rust twee fundamentele regels:

  1. Je kunt tegelijkertijd een onbeperkt aantal onveranderlijke verwijzingen (&T) naar een waarde hebben.
  2. OF u kunt precies één veranderlijke verwijzing (&mut T) naar een waarde tegelijk hebben.

Je kunt absoluut geen onveranderlijke en veranderlijke referenties combineren voor dezelfde waarde in hetzelfde bereik:

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

Referentiebereik en niet-lexicale levensduur (NLL)

Historisch gezien duurde de reikwijdte van een referentie tot het einde van het blok waarin deze was gemaakt. Tegenwoordig is de compiler van Rust slimmer dankzij Non-Lexical Lifetimes (NLL): het bereik van een referentie eindigt op de laatste regel waarin deze daadwerkelijk wordt gebruikt, en niet noodzakelijkerwijs aan het einde van het blok.

Dit maakt de volgende code perfect geldig:

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

Probeer het zelf

Oefening#rust.m3.l2.e1
Pogingen: 0Laden…

Geef een onveranderlijke referentie van s1 door aan de functie berekenen_lengte met behulp van het &-symbool.

Editor laden…
Toon hint

Vervang `/* TODO \_/`door`&s1` om een ​​onveranderlijke verwijzing naar de string door te geven.

Oplossing beschikbaar na 3 pogingen

Oefening#rust.m3.l2.e2
Pogingen: 0Laden…

Maak de variabele s veranderlijk (laten we mut s) en geef een veranderlijke verwijzing (&mut s) door aan de wijzigingsfunctie, zodat deze de string kan wijzigen.

Editor laden…
Toon hint

Gebruik `let mut s`in plaats van`let s`en roep`change(&mut s);` aan.

Oplossing beschikbaar na 3 pogingen

Oefening#rust.m3.l2.e3
Pogingen: 0Laden…

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.

Editor laden…
Toon hint

Assign `let r1 = &s;` and `let r2 = &s;` to obtain two immutable references, then print them with `println!("{} {}", r1, r2);`.

Oplossing beschikbaar na 3 pogingen