Da trilha de Rust Este conceito ainda não saiu como card do dia. ir para o card de hoje

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> aloca T no heap e mantém um ponteiro de tamanho fixo na pilha.
  • Tipos recursivos precisam de Box para ter tamanho conhecido em tempo de compilação.
  • Box<dyn Trait> permite armazenar qualquer tipo que implemente Trait na mesma coleção.
  • dyn Trait usa despacho dinâmico (vtable); genéricos usam despacho estático.
  • Box libera a memória automaticamente quando sai de escopo (Drop).
box_heap.rs
// 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());
    }
}

Exercícios

  1. 1
    Fácil

    Box simples

    Crie um Box<i32> com o valor 10 e imprima o valor desreferenciado. Depois, modifique o valor para 20 e imprima novamente.

    Resolver
  2. 2
    Médio

    Lista encadeada recursiva

    Implemente uma lista encadeada simples usando enum e Box. A lista deve ter um método tamanho que retorna o número de elementos. Crie uma lista com os valores 10, 20 e 30 e imprima o tamanho e o primeiro elemento.

    Resolver
  3. 3
    Desafio

    Trait objects e polimorfismo

    Defina um trait Forma com métodos area() -> f64 e nome() -> String. Implemente para Circulo e Retangulo. Crie um vetor de Box<dyn Forma> com várias formas, calcule a área total e imprima o nome e a área de cada forma. Depois, crie uma função que recebe &dyn Forma e imprime seus dados.

    Resolver

Continue estudando