capypad
0 Tage Serie
rust / intermediate
Snippet

Zyklische Smart Pointer mit Rc und RefCell

Rc (Reference Counting) ermöglicht Mehrfachbesitz, aber Zyklen verursachen Speicherlecks. Schwache Referenzen (Weak) brechen Zyklen - eine Weak erhöht den strong count nicht. Die upgrade()-Methode konvertiert Weak zurück zu Option<Rc>. In dieser Baumstruktur hält parent eine Weak-Referenz, um Kinder nicht zu behalten, während Kinder starke Rc-Referenzen zu ihrem Parent halten. Rc::downgrade erstellt eine Weak aus einer Rc, und der Ausleihprüfer stellt sicher, dass keine Referenzzyklen zur Kompilierzeit existieren.

snippet.rs
rust
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
use std::cell::RefCell;
use std::rc::{Rc, Weak};
 
#[derive(Debug)]
struct Node {
value: i32,
children: RefCell<Vec<Rc<Node>>>,
parent: RefCell<Weak<Node>>,
}
 
impl Node {
fn new(value: i32) -> Rc<Self> {
Rc::new(Node {
value,
children: RefCell::new(Vec::new()),
parent: RefCell::new(Weak::new()),
})
}
 
fn add_child(&self, child: Rc<Node>) {
self.children.borrow_mut().push(Rc::clone(&child));
*child.parent.borrow_mut() = Rc::downgrade(self);
}
 
fn get_parent(&self) -> Option<Rc<Node>> {
self.parent.borrow().upgrade()
}
}
 
fn main() {
let leaf = Node::new(3);
let branch = Node::new(5);
branch.add_child(Rc::clone(&leaf));
 
println!("Leaf parent: {:?}", leaf.get_parent());
println!("Branch strong count: {}", Rc::strong_count(&branch));
println!("Leaf strong count: {}", Rc::strong_count(&leaf));
}
Erklärung
1
parent: RefCell<Weak<Node>>
Weak verhindert nicht, dass Node verworfen wird; verhindert starke Zyklen
2
Rc::downgrade(self)
Erstellt einen Weak-Zeiger auf Rc; erhöht Referenzcount nicht
3
child.parent.borrow_mut() = Rc::downgrade(self);
Setzt die schwache Parent-Referenz des Kindes auf diesen Knoten
4
self.parent.borrow().upgrade()
Konvertiert Weak zu Option<Rc>; None wenn Parent verworfen wurde