Lecții din modul (1/2)
Regulile de proprietate
Proprietatea este cea mai unică caracteristică a Rust. Permite limbajului să garanteze siguranța memoriei fără a avea nevoie de un Garbage Collector sau de a vă forța să dezalocați manual memoria heap (ca în C sau C++).
Cele trei reguli de proprietate
Gestionarea memoriei în Rust este guvernată de trei reguli simple verificate strict de compilator:
- Fiecare valoare din Rust are o variabilă numită proprietarul său.
- Nu poate exista decât un singur proprietar odată.
- Când proprietarul iese din domeniul de aplicare, valoarea este eliminată automat.
Stack vs Heap
Pentru a înțelege calitatea de proprietar, este important să știți unde se află datele:
- Stiva: stochează date de dimensiune fixă cunoscute în momentul compilării (de exemplu, numere întregi, booleeni). Accesul este extrem de rapid.
- Heap: stochează date de dimensiune dinamică necunoscute în momentul compilării (de exemplu,
String). Alocarea este mai lentă și necesită un pointer stocat pe stivă.
Conceptul de „mutare”
Când atribuim o variabilă alocată în heap unei alte variabile, Rust mută (sau transferă) dreptul de proprietate asupra valorii, invalidând prima variabilă:
let s1 = String::from("ciao");
let s2 = s1; // Ownership of the text moves to s2. s1 is NO longer usable!
// println!("{}", s1); // COMPILATION ERROR! s1 is "borrow of moved value"
println!("{}", s2); // Valid!Acest comportament evită „eroarea dublă gratuită” (încercarea de a elibera aceeași memorie de două ori atunci când iese din domeniul de aplicare), deoarece numai s2 va elibera memoria.
Conceptul de „Clone” (Deep Copy)
Dacă trebuie să copiem în mod explicit întregul conținut al unui String (atât pointerii stivei, cât și datele de text reale din heap), putem folosi metoda .clone(). Acest lucru duplică complet datele din heap, păstrând valabile atât variabila originală, cât și noua, cu prețul unei suprasarcini de performanță pentru noua alocare de memorie:
let s1 = String::from("ciao");
let s2 = s1.clone(); // Deep copy. Both variables remain valid!
println!("s1: {}, s2: {}", s1, s2);Conceptul de „copiere”
Pentru tipurile simple stocate în întregime pe Stiva (cum ar fi numerele întregi i32, booleanele bool, caracterele char), atribuirea realizează o copie superficială automată, ceea ce înseamnă că ambele variabile rămân valabile:
let x = 5;
let y = x; // Copies the value 5 onto the stack. Both variables are usable!
println!("x: {}, y: {}", x, y); // Valid!Încercați-l singur
Declarați un șir s1 care conține textul „hello”. Atribuiți s1 la s2 (pentru a muta proprietatea). În cele din urmă, imprimați s2 folosind println!.
Afișează indiciu
Folosiți `let s2 = s1;` pentru a transfera proprietatea către `s2` și imprimați-l cu `println!('{}', s2);`.
Soluție disponibilă după 3 încercări
Declarați o variabilă întreagă x cu valoarea 5. Atribuiți x lui y (efectuând o copie). În cele din urmă, imprimați atât x cât și y în același println! declaraţie.
Afișează indiciu
Faceți `lasă y = x;` și apoi imprimați ambele valori, de exemplu, `println!('{} {}', x, y);`.
Soluție disponibilă după 3 încercări
Declare a String s1 with the value "Rust". Create a deep copy of s1 in a new variable s2 using the clone method. Finally, print both s1 and s2 separated by a space using the println! macro.
Afișează indiciu
Use `let s2 = s1.clone();` to deep copy the value of `s1` into `s2`, then print them with `println!("{} {}", s1, s2);`.
Soluție disponibilă după 3 încercări