Under The Hood
backend rust Rust 1.75+ (edition 2021)

Rust smart pointers: Box, Rc, Arc

Last updated
Prerequisites:
Rust ownership and borrowing
Understanding of trait objects and interior mutability
  • rust
  • smart-pointers
  • box
  • rc
  • arc
  • ownership

Read at your depth

The practical view

Box<T> gives a value a heap allocation with single ownership: let b = Box::new(5); (*b) dereferences it. It is the tool for recursive types (enum List { Cons(i32, Box<List>) }), trait objects (Box<dyn Draw>), and large data you want off the stack. Rc<T> is reference-counted shared ownership within one thread: let a = Rc::new(value); let b = Rc::clone(&a); — the value is dropped when the last Rc drops. Arc<T> is the thread-safe version (atomic refcount): Arc::clone is cheap and lets multiple threads share a value; use it with Mutex/RwLock for shared mutable state across threads. Box is 'one owner, heap', Rc is 'many owners, one thread', Arc is 'many owners, many threads'.

Legacy vs modern

Thread-shared state: Rc across threads (compile error) vs Arc

Rc's non-atomic refcount is not Send, so sharing state across threads fails to compile; Arc's atomic count makes the same design legal.

before → after
Rc across threads (invalid)
let shared = Rc::new(5);
thread::spawn(move || println!("{shared}"));
// E0277: Rc<int> cannot be sent between threads safely
Arc for cross-thread sharing
let shared = Arc::new(Mutex::new(5));
let handle = thread::spawn({
  let shared = Arc::clone(&shared);
  move || { *shared.lock().unwrap() += 1; }
});

Interview gotchas

Under The Hood — a multi-depth technical interview hub.

Press ⌘ K to search.