Skip to Content
RozdziałyPosiadanieReferencje i pożyczki

Referencje i pożyczki

Przekazywanie wartości przez referencję

  1. Referencja do wartości definiowana jest za pomocą operatora &, np.
    let s = String::from("sample"); let s_ref = &s;
  2. Definicja parametrów w postaci referencji nazywa się pożyczaniem wartości. W takim przypadku funkcja nie posiada pożyczonej wartości i musi ją oddać po zakończeniu działania.
    fn main() { let s1 = String::from("sample"); let s2 = process_text(&s1); // lends the s1 value through a reference println!("{} -> {}", s1, s2) // both s1 and s2 are valid } fn process_text(s: &String) -> String { // borrow s value and return new string s.to_uppercase() }

Mutowalne referencje

  1. Wrócmy do funkcji, która chce przetworzyć podany tekst (tym razem będziemy chcieli skrócić dany tekst), ale spróbujmy zrobić to za pomocą pożyczenia wartości
    fn main() { let mut s1 = String::from("sample text"); process_text(&s1, 4); println!("{}", s1); } fn process_text(s: &String, len : usize ) { s.truncate(len) }
  2. Uruchom program i zastanów się na błędami kompilacji
  3. Aby poprawić kod, nie tylko zmienna musi być mutowalna, ale również musimy jawnie wypożyczyć wartość w sposób, który umożliwi modyfikację wartości
    fn main() { let mut s1 = String::from("sample text"); process_text(&mut s1, 4); println!("{}", s1); } fn process_text(s: &mut String, len : usize) { s.truncate(len) }

Praca z referencjami

Reguły dotyczące referencji

W dowolnym momencie programu, dla jednej wartości możemy mieć tylko jeden z poniższych przypadków:

  • jedną mutowalną referencję,
  • dowolną liczbę niemutowalnych referencji.

Ponadto wszystkie odwołania muszą być ważne, ie. muszą odnosić się do wartości, które nie są poza zakresem.

Uruchom kolejne fragmenty kodu i wyjaśnij, której reguły nie spełnia

let mut s = String::from("sample"); let s1 = &mut s; let s2 = &mut s; println!("{}, {}", s1, s2);
let mut s = String::from("sample"); let s1 = &mut s; let s2 = &s; println!("{}, {}", s1, s2);
let mut s = String::from("sample"); let s1 = &mut s; let s2 = s; println!("{}, {}", s1, s2);
fn main() { let s = generate_ref_to_string(); } fn generate_ref_to_string() -> &String { &String::from("dangling text") }

Ćwiczenie - Popraw kod

  1. Popraw poniższy kod tak, aby się skompilował, możesz tylko zmienić kolejność linii w funkcji main. Wyjaśnij dlaczego kod po zmianach jest poprawny.
    fn main() { let mut x = 100; let y = &mut x; let z = &mut x; *y += 100; *z += 1000; assert_eq!(x, 1200); }
  2. Popraw kod jedynie poprzez dodawanie lub usuwanie referencji
    fn main() { let data = "Rust is great!".to_string(); get_char(data); string_uppercase(&data); } // Should not take ownership fn get_char(data: String) -> char { data.chars().last().unwrap() } // Should take ownership fn string_uppercase(mut data: &String) { data = &data.to_uppercase(); println!("{}", data); }

Źródło: powyższe zadania pochodzą z oficjalnych ćwiczeń rustlings, dostępnych w repozytorium https://github.com/rust-lang/rustlings/. Znajdziesz tam dużo więcej podobnych zadań.

Last updated on