Box nos permite almacenar datos en el montón contrario al esquema predeterminado de Rust para almacenar como una pila.
La caja se utiliza básicamente para:
- Para asignación dinámica de memoria para variables.
- Cuando hay muchos datos que necesitamos transferir y no queremos que se copien.
Vamos a crear una caja para almacenar el valor i32 en un montón.
Ejemplo:
Rust
fn main() { let num = Box::new(4); println!("num = {}", num); }
Producción:
num = 4
Usando Box<T> para el tipo recursivo:
Usaremos una lista de contras para crear una lista de valores. cons list toma dos valores, el primero es el valor actual y el otro es el siguiente valor, realiza una llamada recursiva a la función cons para generar una lista, donde la condición base para la llamada recursiva es Nil.
Ejemplo:
Rust
enum List { Cons(i32, List), Nil, } use crate::List::{Cons, Nil}; fn main() { let list = Cons(1, Cons(2, Cons(3, Nil))); }
No se compilará porque el tamaño de la variable Lista no se puede determinar antes de la compilación.
Producción:
rustc -o main main.rs error[E0072]: recursive type `List` has infinite size --> main.rs:1:1 | 1 | enum List { | ^^^^^^^^^ recursive type has infinite size 2 | Cons(i32, List), | ---- recursive without indirection | = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable error[E0391]: cycle detected when processing `List` --> main.rs:1:1 | 1 | enum List { | ^^^^^^^^^ | = note: ...which again requires processing `List`, completing the cycle = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, def_id: None }, value
Hay un error que indica que la Lista tiene un tamaño infinito porque el compilador no puede determinar el tamaño de la Lista durante la compilación. Por lo tanto, usaremos un puntero a la lista en lugar de la lista en sí para solucionar este error. Dado que el tamaño del puntero se fija independientemente del tipo de datos al que apunta, el compilador puede determinar su tamaño durante la compilación. Veamos esta implementación usando Box<T>.
Ejemplo:
Rust
// for printing complex data types #[derive(Debug)] enum List { Cons(i32, Box<List>), Nil, } use crate::List::{Cons, Nil}; fn main() { let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil)))))); println!("{:?}",list) }
Producción:
Cons(1, Cons(2, Cons(3, Nil)))