Rust Memória Avançado
Box e heap
Em Rust, dados na pilha têm tamanho fixo conhecido em tempo de compilação. Quando precisamos de um valor cujo tamanho só é conhecido em tempo de execução, usamos Box<T>, que aloca o valor no heap e guarda na pilha apenas um ponteiro. Isso permite criar tipos recursivos (como uma lista encadeada) e trait objects (dyn Trait), que armazenam qualquer tipo que implemente um trait, apagando o tipo concreto.
Box<T> é um ponteiro inteligente que possui o valor no heap. Quando o Box sai de escopo, o valor é desalocado automaticamente. Além disso, Box<dyn Trait> permite despacho dinâmico: a chamada de método é resolvida em tempo de execução via vtable, ao contrário do despacho estático dos genéricos.
Neste card, você vai aprender a usar Box para quebrar ciclos de tamanho infinito, criar listas encadeadas e armazenar diferentes tipos que compartilham um trait em uma mesma coleção.
Pontos-chave
Box<T>alocaTno heap e mantém um ponteiro de tamanho fixo na pilha.- Tipos recursivos precisam de
Boxpara ter tamanho conhecido em tempo de compilação. Box<dyn Trait>permite armazenar qualquer tipo que implementeTraitna mesma coleção.dyn Traitusa despacho dinâmico (vtable); genéricos usam despacho estático.Boxlibera a memória automaticamente quando sai de escopo (Drop).
// Exemplo: Box, tipos recursivos e trait objects
trait Animal {
fn som(&self) -> String;
}
struct Cachorro;
struct Gato;
impl Animal for Cachorro {
fn som(&self) -> String { "Woof".to_string() }
}
impl Animal for Gato {
fn som(&self) -> String { "Miau".to_string() }
}
// Tipo recursivo: lista encadeada
enum Lista<T> {
No(T, Box<Lista<T>>),
Fim,
}
impl<T> Lista<T> {
fn novo() -> Self { Lista::Fim }
fn push(self, valor: T) -> Self {
Lista::No(valor, Box::new(self))
}
}
fn main() {
// Box simples
let x = Box::new(42);
println!("Box: {}", x);
// Lista encadeada
let lista = Lista::novo().push(1).push(2).push(3);
if let Lista::No(v, _) = lista {
println!("Topo da lista: {}", v);
}
// Trait objects
let animais: Vec<Box<dyn Animal>> = vec![
Box::new(Cachorro),
Box::new(Gato),
];
for a in &animais {
println!("Som: {}", a.som());
}
}