Heap Allocation
Sometimes you need to allocate something on the heap. Maybe you don't know its size at compile time, or you need it to live independently of the scope it's in. When you want to allocate something on the heap, there are a few types you can use to do so1.
Boxed values
The most basic, fundamental heap allocation is using Box
.
A boxed value is simply one that lives on the heap instead of the stack.
A Box
is a boxed value, and it's generic: a Box<u32>
is a u32 that's heap-allocated, and a Box<f64>
is a 64-bit float that's heap-allocated.
To construct one, you use the Box::new
constructor.
Often the compiler can infer what type the Box has, but if not, you have to provide type annotations.
Here are two ways to do that:
#![allow(unused)] fn main() { let x: Box<u32> = Box::new(42); let y = Box::<f64>::new(4.2); }
To move a value back onto the stack, out of the box, you can dereference it:
#![allow(unused)] fn main() { let x: Box<u32> = Box::new(42); let y = *x; // y is now a u32 on the stack }
Vecs
Sometimes you just need to build a list of things.
You do this with Vec
, which is the type for dynamically sized arrays in Rust.
(Rust's arrays are of fixed size.)
#![allow(unused)] fn main() { let mut parrots: Vec<&str> = Vec::new(); parrots.push("Shivers"); parrots.push("Tweety"); parrots.push("Dinner"); println!("parrots: {:?}", parrots); }
You can also do it inline, using the vec!
macro:
#![allow(unused)] fn main() { let parrots = vec!["Shivers", "Tweety", "Dinner"]; println!("parrots: {:?}", parrots); }
You can also iterate over the elements of a Vec:
#![allow(unused)] fn main() { let parrots = vec!["Shivers", "Tweety", "Dinner"]; for parrot in parrots.iter() { println!("{} says hi.", parrot); } }
Other collection types
The standard library has a variety of other collection types, which are helpful for just about anything you need. The std::collections docs have a lot of information about the types available and when you would want to use each.
As a sampling:
Vec
HashMap
andBTreeMap
HashSet
andBTreeSet
We won't go into the details on this page.
Exercise: Write a small program which constructs a HashMap with pirate ship names as keys and their crew sizes as values. For example, "Black Pearl" could have 3 crew members. Iterate over the elements of the hashmap and print each ship with its crew size.
You can also use raw pointers and unsafe Rust. We're not going to talk about that here, because you should almost always avoid it.