# Rust Smart Pointer Cheatsheet Rust's smart pointers enhance the ownership model, providing additional functionality for memory management. Below is a concise reference for the most common smart pointers, their purposes, use cases, and examples. ## Summary Table | Smart Pointer | Description | Use Cases | Example | |---------------|-------------|-----------|---------| | `Box<T>` | Heap-allocated value with single ownership | Large data, recursive types | `let x = Box::new(5);` | | `Rc<T>` | Reference-counted pointer for shared ownership (single-threaded) | Graphs, multiple owners | `let a = Rc::new(5); let b = Rc::clone(&a);` | | `Arc<T>` | Atomic reference-counted pointer for shared ownership (multi-threaded) | Cross-thread data sharing | `let a = Arc::new(5); let b = Arc::clone(&a);` | | `RefCell<T>` | Interior mutability with runtime borrow checking | Mutating data in immutable contexts | `let x = RefCell::new(5); *x.borrow_mut() = 10;` | | `Mutex<T>` | Mutual exclusion for shared mutable state (multi-threaded) | Synchronizing access to shared data | `let m = Mutex::new(5); *m.lock().unwrap() = 10;` | | `RwLock<T>` | Read-write lock for multiple readers or one writer | Efficient concurrent access with more reads than writes | `let lock = RwLock::new(5); let r = lock.read().unwrap();` | | `Cell<T>` | Interior mutability for `Copy` types | Simple mutable state without borrow checking | `let c = Cell::new(5); c.set(10);` | ## Key Points - **Purpose**: Smart pointers extend Rust's ownership system with features like heap allocation, shared ownership, and mutability control. - **Deref Trait**: Most implement `Deref`, allowing use of `*` or direct method calls on the underlying data. - **Drop Trait**: Automatically handles cleanup (e.g., deallocation) when the smart pointer goes out of scope. - **Selection**: Choose based on ownership needs (single vs. multiple), thread safety, and mutability requirements. - **Overhead**: Be aware of runtime costs like reference counting (`Rc<T>`, `Arc<T>`), runtime borrow checks (`RefCell<T>`), or locking (`Mutex<T>`, `RwLock<T>`). ## Usage Examples ### `Box<T>` ```rust let x = Box::new(5); // Allocates 5 on the heap println!("{}", *x); // Prints: 5 ``` ### `Rc<T>` ```rust use std::rc::Rc; let a = Rc::new(5); let b = Rc::clone(&a); println!("{}, {}", a, b); // Prints: 5, 5 ``` ### `Arc<T>` ```rust use std::sync::Arc; use std::thread; let a = Arc::new(5); let b = Arc::clone(&a); thread::spawn(move || println!("{}", b)).join().unwrap(); // Prints: 5 ``` ### `RefCell<T>` ```rust use std::cell::RefCell; let x = RefCell::new(5); *x.borrow_mut() = 10; println!("{}", *x.borrow()); // Prints: 10 ``` ### `Mutex<T>` ```rust use std::sync::Mutex; let m = Mutex::new(5); { let mut num = m.lock().unwrap(); *num = 10; } println!("{:?}", m); // Prints: Mutex { data: 10 } ``` ### `RwLock<T>` ```rust use std::sync::RwLock; let lock = RwLock::new(5); { let r1 = lock.read().unwrap(); let r2 = lock.read().unwrap(); println!("{}, {}", r1, r2); // Prints: 5, 5 } ``` ### `Cell<T>` ```rust use std::cell::Cell; let c = Cell::new(5); c.set(10); println!("{}", c.get()); // Prints: 10 ``` This cheatsheet provides a quick reference for working with Rust smart pointers effectively.