diff --git a/src/std/rc.md b/src/std/rc.md index 40cdc1ab..bef85e41 100644 --- a/src/std/rc.md +++ b/src/std/rc.md @@ -15,18 +15,52 @@ fn main() { } ``` -If you need to mutate the data inside an `Rc`, you will need to wrap the data in -a type such as [`Cell` or `RefCell`][2]. See [`Arc`][3] if you are in a multi-threaded -context. +* If you need to mutate the data inside an `Rc`, you will need to wrap the data in + a type such as [`Cell` or `RefCell`][2]. +* See [`Arc`][3] if you are in a multi-threaded context. +* You can *downgrade* a shared pointer into a [`Weak`][4] pointer to create cycles + that will get dropped. [1]: https://doc.rust-lang.org/std/rc/struct.Rc.html [2]: https://doc.rust-lang.org/std/cell/index.html [3]: ../concurrency/shared_state/arc.md +[4]: https://doc.rust-lang.org/std/rc/struct.Weak.html
* Like C++'s `std::shared_ptr`. * `clone` is cheap: creates a pointer to the same allocation and increases the reference count. * `make_mut` actually clones the inner value if necessary ("clone-on-write") and returns a mutable reference. +* You can `downgrade()` a `Rc` into a *weakly reference-counted* object to + create cycles that will be dropped properly (likely in combination with + `RefCell`). + +```rust,editable +use std::rc::{Rc, Weak}; +use std::cell::RefCell; + +#[derive(Debug)] +struct Node { + value: i64, + parent: Option>>, + children: Vec>>, +} + +fn main() { + let mut root = Rc::new(RefCell::new(Node { + value: 42, + parent: None, + children: vec![], + })); + let child = Rc::new(RefCell::new(Node { + value: 43, + children: vec![], + parent: Some(Rc::downgrade(&root)) + })); + root.borrow_mut().children.push(child); + + println!("graph: {root:#?}"); +} +```