W Rust nie ma klasycznego Garbage Collectora, dlatego do zarządzania własnością skomplikowanych struktur wykorzystuje się wskaźniki inteligentne (smart pointers). Najczęściej używane to:
Box<T> — alokuje pamięć dla obiektu na stercie i przekazuje jej własność. Używane w przypadkach, gdy rozmiar danych nie jest znany w czasie kompilacji lub gdy wymagany jest przenaszalny, ale unikalny zasób.
Rc<T> (Reference Counted) — zliczanie referencji, pozwala kilku zmiennym „dzielić” własność niezmiennych danych (tylko w kontekście jednowątkowym).
Arc<T> (Atomic Reference Counted) — również implementuje zliczanie referencji, ale atomowe; zastosowanie dopuszczalne w programach wielowątkowych.
RefCell<T> — zapewnia "wewnętrzną mutowalność" własności w czasie wykonywania, pozwalając na zmianę zawartości nawet przez niezmienny wskaźnik, ale tylko w jednym wątku (nie jest bezpieczne dla wątków!).
Przykład:
use std::rc::Rc; let a = Rc::new(vec![1,2,3]); let b = Rc::clone(&a); // Teraz zarówno a, jak i b są właścicielami tych samych danych
Czy można używać Rc<T> w kodzie wielowątkowym, jeśli wszystkie wątki tylko odczytują dane? Wyjaśnij.
Odpowiedź: Nie, nie można! Mimo że Rc<T> pozwala tylko na niezmienny dostęp do danych, sam kontener Rc<T> nie jest bezpieczny dla wątków, ponieważ wewnętrzna liczba referencji nie jest chroniona przed wyścigami danych. Do tego służy Arc<T> — jego wewnętrzny licznik jest bezpieczny dla wątków.
Przykład:
// Następujący kod nie skompiluje się! use std::thread; use std::rc::Rc; let five = Rc::new(5); for _ in 0..10 { let five = Rc::clone(&five); thread::spawn(move || { println!("{}", five); }); }
Historia
Historia
Historia
W module logiki biznesowej używano RefCell<T> do organizacji mutowalnego dostępu do danych, które również były przekazywane przez Arc<T> między wątkami. Ale próba połączenia RefCell<T> i Arc<T> doprowadziła do wyścigów i paniki podczas wykonywania. W przypadku wersji bezpiecznej dla wątków należało użyć Mutex<T> lub RwLock<T> zamiast RefCell<T>.