Box<T>

Box es un puntero propio de datos en el heap:

fn main() {
    let five = Box::new(5);
    println!("five: {}", *five);
}
5StackHeapfive

Box<T> implementa Deref<Target = T>, lo que significa que puedes llamar a métodos desde T directamente en un Box<T>.

Los tipos de datos recursivos o los tipos de datos con tamaños dinámicos deben utilizar un Box:

#[derive(Debug)]
enum List<T> {
    /// A non-empty list: first element and the rest of the list.
    Element(T, Box<List<T>>),
    /// An empty list.
    Nil,
}

fn main() {
    let list: List<i32> =
        List::Element(1, Box::new(List::Element(2, Box::new(List::Nil))));
    println!("{list:?}");
}
StackHeaplistElement1Element2Nil
This slide should take about 10 minutes.
  • Box is like std::unique_ptr in C++, except that it’s guaranteed to be not null.

  • Un Box puede resultar útil en los siguientes casos:

    • Si tienes un tipo cuyo tamaño no se conoce durante la compilación, pero el compilador de Rust quiere saber el tamaño exacto.
    • Si quieres transferir la propiedad de una gran cantidad de datos. Para evitar que se copien grandes cantidades de datos en la stack, almacena los datos del heap en un Box para que solo se mueva el puntero.
  • Si no se utiliza Box e intentamos insertar un List directamente dentro de List, el compilador no calcularía un tamaño fijo de la estructura en la memoria (List tendría un tamaño infinito).

  • Box resuelve este problema, ya que tiene el mismo tamaño que un puntero normal y solo apunta al siguiente elemento de la List en el heap.

  • Elimina Box de la definición de la lista y muestra el error del compilador. “Recursivo con indirección” es una sugerencia de que puedes usar un Box o referencia de algún tipo, en lugar de almacenar un valor directamente.

More to Explore

Optimización de la Memoria

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

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

Box no puede estar vacío, por lo que el puntero siempre es válido y no null. Esto permite que el compilador optimice el diseño de la memoria:

StackHeaplistElement1Element2