Box
Box<T> is the simplest smart pointer. It puts a value on the heap and keeps a small pointer on the stack.
Box<T>
Box::new(x) moves x onto the heap. The box owns that value, just like a String owns its text. A box moves on assignment, and when the box goes out of scope, the heap value is freed.
let b = Box::new(5);let c = b; // the box moves to cprintln!("{c}"); // 5Dereferencing a Box
Use *b to get the value inside. Methods work through the box on their own, so b.len() just works.
let mut b = Box::new(10);*b += 1; // change the value insidelet s = Box::new(String::from("hey"));println!("{} {}", b, s.len()); // 11 3Recursive types
A type that holds itself directly would have infinite size. Rust can't lay it out and reports E0072. A Box has a fixed size (one pointer), so it breaks the loop.
enum List { Cons(i32, Box<List>), Nil,}Wrapping in Option alone does not help, because Option<List> still holds a whole List.
Box<dyn Trait>
Different types can have different sizes, so a Vec can't hold them directly. Box<dyn Trait> holds any type that implements the trait, and every box has the same size.
trait Speak { fn say(&self) -> &str; }struct Dog;struct Cat;impl Speak for Dog { fn say(&self) -> &str { "woof" } }impl Speak for Cat { fn say(&self) -> &str { "meow" } }let pets: Vec<Box<dyn Speak>> = vec![Box::new(Dog), Box::new(Cat)];println!("{}", pets[1].say()); // meowEach box calls the say of the type inside it.
Remember
Box::newputs a value on the heap; the box is its one owner.*breads the value; methods work through the box.- E0072 means a type contains itself; add a
Box. Box<dyn Trait>lets one list hold many types.