Rc and Arc
Rc and Arc let more than one owner share the same value, counting how many are still using it before cleaning up.In this page:
Sharing Data with Rc
Rc::new(value) wraps a value for shared ownership; calling .clone() on it produces another owner pointing to the same data and increments an internal reference count.
Example: Sharing Data with Rc
use std::rc::Rc;
fn main() {
let shared = Rc::new(String::from("shared data"));
let owner_two = Rc::clone(&shared);
println!("{} and {}", shared, owner_two);
println!("Reference count: {}", Rc::strong_count(&shared));
}
Login to try C/C++/Java/PHP code in the editor
Rc Clone Is Cheap
Cloning an Rc does not deep-copy the underlying data -- it only increments the reference count, making it a very cheap operation regardless of how large the shared data is.
Example: Rc Clone Is Cheap
use std::rc::Rc;
fn main() {
let data = Rc::new(vec![1, 2, 3, 4, 5]);
let clone_a = Rc::clone(&data);
let clone_b = Rc::clone(&data);
println!("Count: {}", Rc::strong_count(&data));
println!("{:?}", clone_a);
println!("{:?}", clone_b);
}
Login to try C/C++/Java/PHP code in the editor
Using Arc for Thread Safety
Arc<T> behaves like Rc<T> but uses atomic operations for its reference count, making it safe to share across multiple threads, unlike plain Rc.
Example: Using Arc for Thread Safety
use std::sync::Arc;
use std::thread;
fn main() {
let shared = Arc::new(String::from("shared across threads"));
let shared_clone = Arc::clone(&shared);
let handle = thread::spawn(move || {
println!("From thread: {}", shared_clone);
});
handle.join().unwrap();
println!("From main: {}", shared);
}
Login to try C/C++/Java/PHP code in the editor
Value Dropped When Count Reaches Zero
The underlying data wrapped by Rc/Arc is only actually freed once every owner has been dropped and the reference count falls to zero, which happens automatically without manual bookkeeping.
Example: Value Dropped When Count Reaches Zero
use std::rc::Rc;
fn main() {
let a = Rc::new(10);
println!("Count after creating a: {}", Rc::strong_count(&a));
{
let _b = Rc::clone(&a);
println!("Count with b alive: {}", Rc::strong_count(&a));
}
println!("Count after b dropped: {}", Rc::strong_count(&a));
}
Login to try C/C++/Java/PHP code in the editor
- Trying to mutate data inside a plain
Rcdirectly --Rconly allows shared, immutable access on its own. - Using
Rcacross multiple threads, whenArc(atomic reference counting) is required for thread safety. - Creating a reference cycle with
Rc(two values owning each other), which leaks memory since the count never reaches zero.
Rc<T>(Reference Counted) enables multiple owners of the same heap-allocated value within a single thread.Arc<T>(Atomically Reference Counted) is the thread-safe equivalent ofRc, usable across multiple threads..clone()on anRc/Arcincreases the reference count rather than deep-copying the underlying data.- The value is only actually dropped once its reference count reaches zero.
Chapter Quiz — Complete all 7 topics to unlock
0/7 topics done
Complete these topics first: