In this lesson, you will learn how to bypass the heap indirection of a Box to reclaim ownership of the value it holds.
The Nature of the Box
When you place a value on the heap using Box<T>, the stack holds only a pointer to that heap memory. Typically, if you try to move a value out of a Box, you are hindered by the borrow checker because the Box owns the heap allocation—if you moved the value out, the Box would be left in an "uninitialized" state, which violates Rust's safety guarantees.
Destructuring and Moving
If you have a Box<T>, you can move the value out only if you consume the Box itself. This is most commonly achieved through destructuring. By matching on the Box or calling a method that takes self by value, you effectively "break" the container and take ownership of the inner data.
Consider this example:
fn main() {
let boxed_value = Box::new(String::from("Hello, Heap!"));
// We consume the Box to move the String onto the stack
let unboxed_value = *boxed_value;
// The Box is gone, and the memory is freed.
// The String now lives on the stack.
println!("{}", unboxed_value);
}
Why it works
When you dereference the Box using the * operator in a context where ownership is expected (like an assignment to a new variable), the compiler recognizes that you are taking the value out of the container. Because the Box itself is consumed (it no longer exists after the move), the compiler knows that the heap memory is no longer being tracked by that specific Box instance.
Crucially, this is only possible if the type T inside the Box has a known size at compile time (which Box ensures) and the movement doesn't leave the Box in a partially initialized state. By moving the value, you move the responsibility of dropping that heap memory from the Box to the new owner of the unboxed value.
Key Takeaway: Moving out of a Box consumes the container, allowing you to transfer ownership of the heap-allocated data back onto the stack, effectively finalizing the lifecycle of the pointer.