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.
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 happensVeranderlijke 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:
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:
- Je kunt tegelijkertijd een onbeperkt aantal onveranderlijke verwijzingen (
&T) naar een waarde hebben. - 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:
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 immutableReferentiebereik 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:
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 pointProbeer het zelf
Geef een onveranderlijke referentie van s1 door aan de functie berekenen_lengte met behulp van het &-symbool.
Toon hint
Vervang `/* TODO \_/`door`&s1` om een onveranderlijke verwijzing naar de string door te geven.
Oplossing beschikbaar na 3 pogingen
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.
Toon hint
Gebruik `let mut s`in plaats van`let s`en roep`change(&mut s);` aan.
Oplossing beschikbaar na 3 pogingen
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.
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