Rc
Sometimes one value needs more than one owner. For example, two lists might share the same tail. Rc<T> (reference counted) makes that possible in single-threaded code.
Shared ownership
Rc::new(x) puts x on the heap behind a counter. Every Rc that points to it is an owner. An Rc still moves on plain assignment, so use Rc::clone to add an owner.
use std::rc::Rc;let a = Rc::new(String::from("hi"));let b = Rc::clone(&a);println!("{a} {b}"); // hi hiRc::clone
Rc::clone(&a) does not copy the String. It copies a pointer and adds 1 to the counter, so it is cheap. a.clone() does the same thing, but Rc::clone makes it clear that no deep copy happens. Rc::ptr_eq(&a, &b) is true when a and b point at the very same value, not just equal ones.
Reference counting
Rc::strong_count(&a) tells you how many owners exist right now. When an owner is dropped, the count goes down by 1. When it reaches zero, the value inside is dropped.
let a = Rc::new(5);{ let b = Rc::clone(&a); println!("{}", Rc::strong_count(&a)); // 2}println!("{}", Rc::strong_count(&a)); // 1Rc is read-only
Many owners could be reading the value at once. So an Rc only gives shared (&) access. Trying to change the value, like calling push, fails with E0596, even if the variable is mut.
let v = Rc::new(vec![1, 2]);println!("{}", v.len()); // reading is fine// v.push(3); // error E0596The next unit shows how to change shared data with RefCell.
Remember
Rcgives a value many owners.Rc::cloneis cheap: it only bumps a counter.- The value is dropped when the count reaches zero.
- You can read through an
Rc, but not change the value (E0596).