In Rust, most values are stored on the stack by default. The stack is fast and efficient, but it has limitations: all values must have a known, fixed size at compile time, and the stack has limited space. When you need to store data with a size unknown at compile time, or when you have large data that you don't want to copy, you need heap allocation.
Box<T> is Rust's simplest smart pointer for heap allocation. When you create a Box<T>, the value of type T is allocated on the heap, and the Box itself (which is just a pointer) lives on the stack. When the Box goes out of scope, both the pointer and the heap data are deallocated automatically thanks to Rust's ownership system.
Common use cases for Box<T> include:
Box<dyn Trait>)Implement the following types and functions that demonstrate heap allocation with Box<T>:
boxed_value<T>(value: T) -> Box<T> - A generic function that takes any value and returns it boxed on the heap.
unbox<T>(boxed: Box<T>) -> T - A generic function that takes a boxed value and returns the inner value, moving it out of the box.
List enum - A recursive linked list type:
Nil - represents the end of the listCons(i32, Box<List>) - a node containing a value and a pointer to the next nodeList::new() -> List - Creates an empty list (Nil).
List::prepend(self, value: i32) -> List - Adds a value to the front of the list, returning a new list.
List::len(&self) -> usize - Returns the number of elements in the list.
List::sum(&self) -> i32 - Returns the sum of all elements in the list.
List::to_vec(&self) -> Vec<i32> - Converts the list to a Vec, preserving order.
LargeData struct - A struct with a large array data: [u8; 1000] to demonstrate boxing large data.
box_large_data(data: LargeData) -> Box<LargeData> - Boxes a large data structure.
modify_boxed<T, F>(boxed: &mut Box<T>, f: F) - Takes a mutable reference to a boxed value and applies a function to modify the inner value. F: FnOnce(&mut T).
// Boxing and unboxing
let boxed = boxed_value(42);
assert_eq!(*boxed, 42);
let value = unbox(boxed);
assert_eq!(value, 42);
// Recursive list
let list = List::new()
.prepend(3)
.prepend(2)
.prepend(1);
assert_eq!(list.len(), 3);
assert_eq!(list.sum(), 6);
assert_eq!(list.to_vec(), vec![1, 2, 3]);
// Boxing large data
let large = LargeData { data: [0; 1000] };
let boxed_large = box_large_data(large);
assert_eq!(boxed_large.data[0], 0);
// Modifying boxed values
let mut boxed_num = Box::new(10);
modify_boxed(&mut boxed_num, |n| *n += 5);
assert_eq!(*boxed_num, 15);Box::new(value) to create a boxed value* operator dereferences a Box to access the inner valueList, you must use Box to give the type a known sizeList::prepend method should create a new Cons node with the current list boxed as the tailmodify_boxed, use &mut **boxed or boxed.as_mut() to get a mutable reference to the inner valueBox<T> implements Deref and DerefMut, so you can often use it like a regular reference