Reading — step 1 of 5
Learn
~1 min readSmart Pointers and Interior Mutability
Smart pointers wrap a value with extra semantics (heap allocation, reference counting, etc.).
Box<T> — single owner, heap-allocated:
let b: Box<i32> = Box::new(5);
println!("{}", *b); // 5 — auto-deref
// Useful for recursive types:
enum List {
Cons(i32, Box<List>),
Nil,
}
Without Box, the recursive enum would have infinite size — Box has known pointer size.
Rc<T> — single-threaded shared ownership (Reference Counted):
use std::rc::Rc;
let shared = Rc::new("hello");
let a = Rc::clone(&shared); // increments refcount
let b = Rc::clone(&shared);
Rc::strong_count(&shared); // 3
When the last Rc is dropped, the value is freed.
Arc<T> — atomically reference-counted, thread-safe:
use std::sync::Arc;
use std::thread;
let data = Arc::new(vec![1, 2, 3]);
let mut handles = vec![];
for i in 0..3 {
let data = Arc::clone(&data);
handles.push(thread::spawn(move || {
println!("thread {}: {:?}", i, data);
}));
}
for h in handles { h.join().unwrap(); }
Comparison:
Box<T>— single owner, single thread, fastRc<T>— multiple owners, single thread, fastArc<T>— multiple owners, multi-thread, slightly slower (atomic ops)
Reference cycles with Rc/Arc cause memory leaks. Use Weak<T> for parent pointers in tree-shaped data:
use std::rc::{Rc, Weak};
use std::cell::RefCell;
struct Node {
value: i32,
parent: RefCell<Weak<Node>>, // weak — doesn't keep parent alive
children: RefCell<Vec<Rc<Node>>>,
}
Discussion
Ask a question, share an insight, or help someone who’s stuck.
Sign in to post a comment or reply.
Loading…