19.5 Rc<T>
: Reference Counting for Shared Ownership
Rust’s ownership model ensures that each value has a single owner by default. However, some cases require multiple owners. Consider a graph where multiple edges point to the same node. Using Box<T>
would mean copying data or enforcing a single exclusive owner, neither of which matches the intended semantics.
Rc<T>
(Reference Counted) addresses this by allowing multiple pointers to share ownership of the same heap data. The data remains alive until all Rc<T>
instances are dropped, at which point it’s freed automatically.
19.5.1 Why Rc<T>
Is Needed
Without Rc<T>
, cloning a Box<T>
creates independent copies rather than shared ownership. For large, immutable data or complex, shared structures, this is inefficient and semantically incorrect. Rc<T>
uses a reference count to share ownership without copying data.
19.5.2 How Rc<T>
Works
Rc<T>
stores both the data and a reference count in a single heap allocation. Each time you clone an Rc<T>
, it increments the count. Dropping an Rc<T>
decrements the count. When the count reaches zero, the data is freed.
Overhead:
Rc<T>
adds a small runtime cost for maintaining the reference count. Still, this is typically more efficient than copying large data multiple times.
Single-Threaded Only:
Rc<T>
is not thread-safe. For cross-thread sharing, use Arc<T>
.
Immutability:
Rc<T>
enables shared ownership but not shared mutability. To mutate shared data, combine Rc<T>
with interior mutability tools like RefCell<T>
.
Example: Graph Nodes
use std::rc::Rc; #[derive(Debug)] struct Node { value: i32, } fn main() { let node = Rc::new(Node { value: 42 }); let edge1 = Rc::clone(&node); let edge2 = Rc::clone(&node); println!("Node via edge1: {:?}", edge1); println!("Node via edge2: {:?}", edge2); println!("Reference count: {}", Rc::strong_count(&node)); }
19.5.3 Limitations and Trade-Offs
- Runtime overhead for reference counting.
- Not thread-safe; use
Arc<T>
if you need multi-threaded shared ownership. - Immutability enforced at the type level unless combined with interior mutability types.