Smart Pointers

Box<T>

Box<T> is the fundamental single-owner smart pointer in the Rust standard library. It allocates a value of type T on the heap while storing a single non-null pointer (Unique<T>) on the stack. When the Box<T> goes out of scope, its Drop implementation drops the inner T and deallocates the heap memory block.

Memory Representation

For any Sized type T, Box<T> has the exact same size and alignment as &T or *mut T (8 bytes on 64-bit targets) and carries zero runtime overhead beyond the heap allocation itself. Because its internal pointer is guaranteed never to be null, Option<Box<T>> uses niche optimization and also occupies 8 bytes.

Stack (8 bytes)                Heap (size_of::<T>() bytes)
+--------------------+         +---------------------------+
| b: Box<Point>      |         | Point                     |
|   ptr: 0x600001790 +-------> |   x: 10.5 (f64, 8 bytes)  |
+--------------------+         |   y: 20.0 (f64, 8 bytes)  |
                               +---------------------------+
struct Point {
    x: f64,
    y: f64,
}

fn main() {
    let boxed_point = Box::new(Point { x: 10.5, y: 20.0 });

    println!("size of Point:             {} bytes", size_of::<Point>());
    println!("size of Box<Point>:        {} bytes", size_of::<Box<Point>>());
    println!("size of Option<Box<Point>>: {} bytes", size_of::<Option<Box<Point>>>());
    println!("point: ({}, {})", boxed_point.x, boxed_point.y);
}
size of Point:             16 bytes
size of Box<Point>:        8 bytes
size of Option<Box<Point>>: 8 bytes
point: (10.5, 20)

Moving Out of a Box<T> via Dereference

Unlike other smart pointers, Box<T> has special compiler support for dereference move: applying the unary * operator to an owned Box<T> moves the inner value out of the heap allocation onto the stack and immediately frees the empty heap block.

fn main() {
    let heap_text: Box<String> = Box::new(String::from("moved out of box"));
    let stack_text: String = *heap_text;

    println!("stack_text: {}", stack_text);
}
stack_text: moved out of box

Key Box<T> Associated Functions

Function / Method Signature Behavior
Box::new(val) fn new(x: T) -> Box<T> Allocates heap memory and moves x into it
Box::into_raw(b) fn into_raw(b: Box<T>) -> *mut T Consumes the Box and returns a raw pointer without dropping or deallocating T
Box::from_raw(ptr) unsafe fn from_raw(raw: *mut T) -> Box<T> Reconstructs ownership of a Box<T> previously leaked via into_raw
Box::leak(b) fn leak<'a>(b: Box<T>) -> &'a mut T Consumes the Box and returns a mutable reference 'a (often 'static) that lives for the rest of the program
Box::into_pin(b) fn into_pin(boxed: Box<T>) -> Pin<Box<T>> Converts a Box<T> into a pinned heap allocation in place

Controlled Leaking and Reclaiming with into_raw and from_raw

When passing ownership of a Rust heap object to a C library or storing it in an intrusive data structure, Box::into_raw suspends automatic destruction until Box::from_raw reclaims it:

fn main() {
    let boxed = Box::new(vec![10, 20, 30]);
    let raw_ptr: *mut Vec<i32> = Box::into_raw(boxed);

    // Mutate through the raw pointer while Rust automatic drop is suspended:
    unsafe {
        (*raw_ptr).push(40);
    }

    // Reclaim ownership so the Vec and its Box allocation are properly freed:
    let reclaimed: Box<Vec<i32>> = unsafe { Box::from_raw(raw_ptr) };
    println!("reclaimed: {:?}", reclaimed);
}
reclaimed: [10, 20, 30, 40]