Цикл счетов и слабая ссылка в Rust
Сильный счет держит данные живыми, пока на них смотрит хотя бы одно имя. Если два узла хранят друг в друге сильные ссылки, счет у каждого не падает до нуля, хотя остальной код уже не пользуется этой парой. Память под такой парой может не освободиться вовремя.
Слабая ссылка не увеличивает сильный счет: она лишь наблюдает за объектом, пока тот еще жив. Из слабой ссылки можно попытаться получить сильную обратно: результат приходит как необязательное значение, если объект уже исчез, там будет пустой вариант.
Свяжем два узла так, что обратная связь идет через слабую ссылку:
use std::cell::RefCell;
use std::rc::{Rc, Weak};
struct Node {
value: i32,
next: RefCell<Option<Rc<Node>>>,
prev: RefCell<Weak<Node>>,
}
fn main() {
let a = Rc::new(Node {
value: 1,
next: RefCell::new(None),
prev: RefCell::new(Weak::new()),
});
let b = Rc::new(Node {
value: 2,
next: RefCell::new(None),
prev: RefCell::new(Weak::new()),
});
*a.next.borrow_mut() = Some(Rc::clone(&b));
*b.prev.borrow_mut() = Rc::downgrade(&a);
if let Some(up) = b.prev.borrow().upgrade() {
println!("{}", up.value);
}
}
Запись Rc::downgrade дает слабую
сторону от a. Метод upgrade
возвращает сильное имя только пока узел
еще не уничтожен; разбор через if let
обходит оба исхода без извлечения с
принудительной остановкой.
Если бы оба поля держали только сильные
ссылки друг на друга, после выхода из
main пара могла бы остаться в
памяти лишь из-за счетов внутри себя.
Слабое поле не мешает освободить узел,
когда на него больше не смотрят снаружи.
Дана структура:
struct Item {
id: i32,
}
Опишите два узла со ссылкой вперед через
сильный счет и назад через слабую, свяжите
их и выведите id предка, если
удалось восстановить сильное имя на
него.
Дано число:
let num = 4;
Сохраните литерал в узле под сильным
счетом, положите слабую ссылку на этот
узел в отдельную переменную и через
if let выведите значение после
восстановления сильного имени.
Скажите, почему слабая ссылка одна не удерживает значение в куче, когда сильный счет уже стал нулем.