---
title: Box, Rc, Arc
url: https://doc.liz6.com/en/rust/04-smart-pointers-and-memory/01-Box-Rc-Arc
locale: en
area: rust
tags:
- Box
- Rc
- Arc
- Weak
- reference counting
- heap allocation
- recursive type
- DST
- Drop
- atomic
- rust
- smart-pointers-and-memory
date: 2026-06-30
modified: 2026-07-16
description: Box is single-owner heap allocation (simplest), Rc is single-threaded reference counting (shared ownership), Arc is multi-threaded atomic reference counting. Weak breaks reference cycles; in memory layout, the value and reference count of Rc/Arc are allocated adjacently on the heap—understanding these three is understanding Rust’s "no GC but with reference counting."
---

# Box, Rc, Arc

> Box is single-owner heap allocation (simplest), Rc is single-threaded reference counting (shared ownership), Arc is multi-threaded atomic reference counting. Weak breaks reference cycles; in memory layout, the value and reference count of Rc/Arc are allocated adjacently on the heap—understanding these three is understanding Rust’s "no GC but with reference counting."

## Box<T>: Single-Owner Heap Allocation

```rust
let b = Box::new(42);               // Allocate an i32 on the heap
// stack: [8-byte ptr] → heap: [4-byte value: 42]
```

`Box<T>` is Rust's simplest heap allocation—single owner, no reference counting. When `b` goes out of scope, the heap memory is freed. Similar to C++'s `std::unique_ptr<T>`, but the Rust version doesn't require move semantics keywords—ownership is guaranteed at compile time.

### When to Use Box

1. **Recursive Types**: Rust must know the type size at compile time. `enum List { Cons(i32, List), Nil }` recursion leads to infinite size. Solution: `Cons(i32, Box<List>)`—Box has a fixed size (pointer, 8B), recursion is resolved indirectly via the heap.
2. **Trait Objects**: `Box<dyn Display>` stores any type that implements Display.
3. **Moving Large Values from Stack to Heap**: If you have `[u8; 1000000]`, using `Box::new([0u8; 1000000])` places only an 8-byte pointer on the stack.
4. **DST (Dynamically Sized Type)**: `Box<[T]>`, `Box<str>`, `Box<dyn Trait>`.

## Rc<T>: Single-Threaded Reference Counting

```rust
use std::rc::Rc;
let a = Rc::new(vec![1, 2, 3]);     // strong_count = 1
let b = Rc::clone(&a);              // strong_count = 2, does not copy Vec data!
let c = Rc::clone(&a);              // strong_count = 3
```

Internal layout (allocated adjacently on the heap):
```
heap: [strong_count: usize(8B)] [weak_count: usize(8B)] [T: data]
Rc<T>: ptr → points to the address of T (actually points before strong_count)
```

`Rc::clone` only increments the strong_count—the data is not copied. When the last `Rc<T>` is dropped → strong_count = 0 → data is freed. Rc does not implement `Send`—its reference counting operations are not atomic, and using it across threads will cause data races.

## Arc<T>: Multi-Threaded Reference Counting

```rust
use std::sync::Arc;
let a = Arc::new(vec![1, 2, 3]);
let b = Arc::clone(&a);            // atomic increment → thread-safe
std::thread::spawn(move || {
    println!("{:?}", b);           // b can be moved into thread
});
```

Same internal structure as Rc, but strong/weak count operations use `atomic` instructions. `Arc::clone` is about 10x slower than `Rc::clone` (atomic increment vs non-atomic increment), but it is still extremely fast for heap allocation (~10ns vs ~1ns).

## Weak<T>: Preventing Reference Cycles

```rust
use std::rc::{Rc, Weak};
let strong = Rc::new(42);
let weak: Weak<_> = Rc::downgrade(&strong);  // Does not increase strong_count

drop(strong);                        // strong_count = 0 → data freed
assert!(weak.upgrade().is_none());   // Weak detects data has been freed → None
```

Classic use case: In tree structures, parent nodes store `Weak` references to child nodes. If they stored `Rc`, it would be a reference cycle—parent references child, child references parent, neither can be freed. `Weak` does not prevent data from being freed; it temporarily grants access to the data via the `upgrade()` method (which may return None).

## References

- **Rust Book**: Chapter 15.1-15.4
- **Rustonomicon**: Arc atomicity, reference counting

*Keywords: Box, Rc, Arc, Weak, reference counting, heap allocation, recursive type, DST, Drop, atomic*
