diff --git a/src/SUMMARY.md b/src/SUMMARY.md index 7d91af4307..6121054342 100644 --- a/src/SUMMARY.md +++ b/src/SUMMARY.md @@ -175,6 +175,7 @@ - [HashMap](std/hash.md) - [Alternate/custom key types](std/hash/alt_key_types.md) - [HashSet](std/hash/hashset.md) + - [`Rc`](std/rc.md) - [Std misc](std_misc.md) - [Threads](std_misc/threads.md) diff --git a/src/std/rc.md b/src/std/rc.md new file mode 100644 index 0000000000..d89dd9057b --- /dev/null +++ b/src/std/rc.md @@ -0,0 +1,54 @@ +# `Rc` + +When multiple ownership is needed, `Rc`(Reference Counting) can be used. `Rc` keeps track of the number of the references which means the number of owners of the value wrapped inside an `Rc`. + +Reference count of an `Rc` increases by 1 whenever an `Rc` is cloned, and decreases by 1 whenever one cloned `Rc` is dropped out of the scope. When an `Rc`'s reference count becomes zero, which means there are no owners remained, both the `Rc` and the value are all dropped. + +Cloning an `Rc` never do a deep copy. Cloning creates just another pointer to the wrapped value, and increments the count. + +```rust,editable +use std::rc::Rc; + +fn main() { + let rc_examples = "Rc examples".to_string(); + { + println!("--- rc_a is created ---"); + + let rc_a: Rc = Rc::new(rc_examples); + println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); + + { + println!("--- rc_a is cloned to rc_b ---"); + + let rc_b: Rc = Rc::clone(&rc_a); + println!("Reference Count of rc_b: {}", Rc::strong_count(&rc_b)); + println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); + + // Two `Rc`s are equal if their inner values are equal + println!("rc_a and rc_b are equal: {}", rc_a.eq(&rc_b)); + + // We can use methods of a value directly + println!("Length of the value inside rc_a: {}", rc_a.len()); + println!("Value of rc_b: {}", rc_b); + + println!("--- rc_b is dropped out of scope ---"); + } + + println!("Reference Count of rc_a: {}", Rc::strong_count(&rc_a)); + + println!("--- rc_a is dropped out of scope ---"); + } + + // Error! `rc_examples` already moved into `rc_a` + // And when `rc_a` is dropped, `rc_examples` is dropped together + // println!("rc_examples: {}", rc_examples); + // TODO ^ Try uncommenting this line +} +``` + +### See also + +[std::rc][1] and [Arc][2]. + +[1]: https://doc.rust-lang.org/std/rc/index.html +[2]: https://doc.rust-lang.org/std/sync/struct.Arc.html