# Module std::boxed

1.0.0 · source ·
Expand description

The `Box<T>` type for heap allocation.

`Box<T>`, casually referred to as a ‘box’, provides the simplest form of heap allocation in Rust. Boxes provide ownership for this allocation, and drop their contents when they go out of scope. Boxes also ensure that they never allocate more than `isize::MAX` bytes.

## Examples

Move a value from the stack to the heap by creating a `Box`:

    let val: u8 = 5;
    let boxed: Box<u8> = Box::new(val);

Run

Move a value from a `Box` back to the stack by dereferencing:

    let boxed: Box<u8> = Box::new(5);
    let val: u8 = *boxed;

Run

Creating a recursive data structure:

    #[derive(Debug)]
    enum List<T> {
        Cons(T, Box<List<T>>),
        Nil,
    }

    let list: List<i32> = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Nil))));
    println!("{list:?}");

Run

This will print `Cons(1, Cons(2, Nil))`.

Recursive structures must be boxed, because if the definition of `Cons` looked like this:

ⓘ

    Cons(T, List<T>),

Run

It wouldn’t work. This is because the size of a `List` depends on how many elements are in the list, and so we don’t know how much memory to allocate for a `Cons`. By introducing a `Box<T>`, which has a defined size, we know how big `Cons` needs to be.

## Memory layout

For non-zero-sized values, a `Box` will use the `Global` allocator for its allocation. It is valid to convert both ways between a `Box` and a raw pointer allocated with the `Global` allocator, given that the `Layout` used with the allocator is correct for the type. More precisely, a `value: *mut T` that has been allocated with the `Global` allocator with `Layout::for_value(&*value)` may be converted into a box using `Box::<T>::from_raw(value)`. Conversely, the memory backing a `value: *mut T` obtained from `Box::<T>::into_raw` may be deallocated using the `Global` allocator with `Layout::for_value(&*value)`.

For zero-sized values, the `Box` pointer still has to be valid for reads and writes and sufficiently aligned. In particular, casting any aligned non-zero integer literal to a raw pointer produces a valid pointer, but a pointer pointing into previously allocated memory that since got freed is not valid. The recommended way to build a Box to a ZST if `Box::new` cannot be used is to use `ptr::NonNull::dangling`.

So long as `T: Sized`, a `Box<T>` is guaranteed to be represented as a single pointer and is also ABI-compatible with C pointers (i.e. the C type `T*`). This means that if you have extern “C” Rust functions that will be called from C, you can define those Rust functions using `Box<T>` types, and use `T*` as corresponding type on the C side. As an example, consider this C header which declares functions that create and destroy some kind of `Foo` value:

    /* C header */

    /* Returns ownership to the caller */
    struct Foo* foo_new(void);

    /* Takes ownership from the caller; no-op when invoked with null */
    void foo_delete(struct Foo*);

These two functions might be implemented in Rust as follows. Here, the `struct Foo*` type from C is translated to `Box<Foo>`, which captures the ownership constraints. Note also that the nullable argument to `foo_delete` is represented in Rust as `Option<Box<Foo>>`, since `Box<Foo>` cannot be null.

    #[repr(C)]
    pub struct Foo;

    #[no_mangle]
    pub extern "C" fn foo_new() -> Box<Foo> {
        Box::new(Foo)
    }

    #[no_mangle]
    pub extern "C" fn foo_delete(_: Option<Box<Foo>>) {}

Run

Even though `Box<T>` has the same representation and C ABI as a C pointer, this does not mean that you can convert an arbitrary `T*` into a `Box<T>` and expect things to work. `Box<T>` values will always be fully aligned, non-null pointers. Moreover, the destructor for `Box<T>` will attempt to free the value with the global allocator. In general, the best practice is to only use `Box<T>` for pointers that originated from the global allocator.

Important. At least at present, you should avoid using `Box<T>` types for functions that are defined in C but invoked from Rust. In those cases, you should directly mirror the C types as closely as possible. Using types like `Box<T>` where the C definition is just using `T*` can lead to undefined behavior, as described in rust-lang/unsafe-code-guidelines#198.

## Considerations for unsafe code

Warning: This section is not normative and is subject to change, possibly being relaxed in the future! It is a simplified summary of the rules currently implemented in the compiler.

The aliasing rules for `Box<T>` are the same as for `&mut T`. `Box<T>` asserts uniqueness over its content. Using raw pointers derived from a box after that box has been mutated through, moved or borrowed as `&mut T` is not allowed. For more guidance on working with box from unsafe code, see rust-lang/unsafe-code-guidelines#326.

## Structs

- ThinBox Experimental
  ThinBox.
- Box
  A pointer type that uniquely owns a heap allocation of type `T`.