Rust

Guia Completo de Box<T> em Rust: Alocação Explícita no Heap

7 min de leitura

Guia Completo de Box<T> em Rust: Alocação Explícita no Heap

O que é Box e Por Que Usar? Box é um tipo de dado inteligente (smart pointer) em Rust que aloca valores no heap em vez de na stack. A stack é uma região de memória rápida mas limitada; o heap é maior mas mais lenta. Quando você tem dados de tamanho desconhecido em tempo de compilação ou precisa passar propriedade entre escopos, Box é a ferramenta certa. Rust é uma linguagem de propriedade. Por padrão, valores vivem na stack e são movidos quando atribuídos a novas variáveis. Box envolve um valor e permite que você o trate como um ponteiro — mantendo a semântica de propriedade intacta. Quando o Box sai do escopo, o valor no heap é automaticamente desalocado. Não há garbage collector; a memória é gerenciada por regras determinísticas. Alocação e Propriedade Quando você cria um Box com , Rust aloca memória no heap e retorna um Box que "possui" esse valor. A propriedade funciona normalmente: quando

<h2>O que é Box&lt;T&gt; e Por Que Usar?</h2>

<p>Box&lt;T&gt; é um tipo de dado inteligente (smart pointer) em Rust que aloca valores no heap em vez de na stack. A stack é uma região de memória rápida mas limitada; o heap é maior mas mais lenta. Quando você tem dados de tamanho desconhecido em tempo de compilação ou precisa passar propriedade entre escopos, Box&lt;T&gt; é a ferramenta certa.</p>

<p>Rust é uma linguagem de propriedade. Por padrão, valores vivem na stack e são movidos quando atribuídos a novas variáveis. Box&lt;T&gt; envolve um valor e permite que você o trate como um ponteiro — mantendo a semântica de propriedade intacta. Quando o Box sai do escopo, o valor no heap é automaticamente desalocado. Não há garbage collector; a memória é gerenciada por regras determinísticas.</p>

<pre><code class="language-rust">fn main() {

// Valor na stack

let x = 5;

// Valor no heap via Box

let y = Box::new(5);

println!(&quot;x = {}&quot;, x); // 5

println!(&quot;y = {}&quot;, y); // 5 (Box dereferencia automaticamente em println!)

// Tamanho em bytes

println!(&quot;Size of x: {}&quot;, std::mem::size_of_val(&amp;x)); // 8 (i32)

println!(&quot;Size of y: {}&quot;, std::mem::size_of_val(&amp;y)); // 8 (ponteiro)

}</code></pre>

<h2>Alocação e Propriedade</h2>

<p>Quando você cria um Box com <code>Box::new(valor)</code>, Rust aloca memória no heap e retorna um Box que &quot;possui&quot; esse valor. A propriedade funciona normalmente: quando o Box sai do escopo, o valor é desalocado. Você pode transferir propriedade movendo o Box, ou emprestar uma referência usando <code>&amp;box</code> ou <code>&amp;*box</code>.</p>

<p>Este exemplo mostra transferência de propriedade e borrowing:</p>

<pre><code class="language-rust">struct Pessoa {

nome: String,

idade: u32,

}

fn imprime_pessoa(p: &amp;Pessoa) {

println!(&quot;{}, {} anos&quot;, p.nome, p.idade);

}

fn consome_pessoa(p: Box&lt;Pessoa&gt;) {

println!(&quot;Consumindo: {}&quot;, p.nome);

// Box e seu conteúdo são desalocados aqui

}

fn main() {

let pessoa = Box::new(Pessoa {

nome: &quot;Alice&quot;.to_string(),

idade: 30,

});

// Emprestando referência - pessoa ainda é dona do Box

imprime_pessoa(&amp;pessoa);

// Transferindo propriedade - pessoa perde o Box

consome_pessoa(pessoa);

// println!(&quot;{}&quot;, pessoa.nome); // ERRO: pessoa não existe mais

}</code></pre>

<h2>Casos de Uso Práticos</h2>

<h3>Dados de Tamanho Desconhecido</h3>

<p>Traits em Rust não têm tamanho conhecido em tempo de compilação. Se você quer armazenar diferentes tipos implementando a mesma trait, use <code>Box&lt;dyn Trait&gt;</code>:</p>

<pre><code class="language-rust">trait Animal {

fn fazer_som(&amp;self);

}

struct Cachorro;

struct Gato;

impl Animal for Cachorro {

fn fazer_som(&amp;self) {

println!(&quot;Au au!&quot;);

}

}

impl Animal for Gato {

fn fazer_som(&amp;self) {

println!(&quot;Miau!&quot;);

}

}

fn main() {

let animais: Vec&lt;Box&lt;dyn Animal&gt;&gt; = vec![

Box::new(Cachorro),

Box::new(Gato),

Box::new(Cachorro),

];

for animal in animais {

animal.fazer_som();

}

}</code></pre>

<h3>Estruturas Recursivas</h3>

<p>Tipos recursivos (como árvores ou listas ligadas) precisam de Box para quebrar a dependência circular:</p>

<pre><code class="language-rust">#[derive(Debug)]

enum Nodo {

Vazio,

Com(i32, Box&lt;Nodo&gt;),

}

fn main() {

let lista = Nodo::Com(1, Box::new(

Nodo::Com(2, Box::new(

Nodo::Com(3, Box::new(Nodo::Vazio))

))

));

println!(&quot;{:?}&quot;, lista);

// Com(1, Com(2, Com(3, Vazio)))

}</code></pre>

<h3>Otimização de Performance</h3>

<p>Valores grandes podem degradar performance se copiados frequentemente. Box evita cópias mantendo um ponteiro:</p>

<pre><code class="language-rust">struct DadosGrandes {

vetor: Vec&lt;u32&gt;,

}

impl DadosGrandes {

fn new() -&gt; Self {

DadosGrandes {

vetor: vec![0; 1_000_000],

}

}

}

fn processa(dados: Box&lt;DadosGrandes&gt;) {

println!(&quot;Processando {} elementos&quot;, dados.vetor.len());

}

fn main() {

let dados = Box::new(DadosGrandes::new());

processa(dados); // Apenas o ponteiro é movido, não os milhões de elementos

}</code></pre>

<h2>Dereferência e Coerção</h2>

<p>Box implementa o trait <code>Deref</code>, permitindo acessar o valor através do operador <code>*</code> ou via coerção automática. Rust converte <code>Box&lt;T&gt;</code> em <code>&amp;T</code> automaticamente em contextos onde uma referência é esperada:</p>

<pre><code class="language-rust">fn main() {

let boxed = Box::new(String::from(&quot;Rust&quot;));

// Dereferência explícita

println!(&quot;Comprimento: {}&quot;, (*boxed).len());

// Dereferência implícita (coerção)

println!(&quot;Maiúsculas: {}&quot;, boxed.to_uppercase());

// Modificação via DerefMut

let mut numero = Box::new(42);

*numero += 8;

println!(&quot;Número: {}&quot;, numero);

}</code></pre>

<p>Box também implementa <code>DerefMut</code>, permitindo mutabilidade. Se você precisa modificar o valor dentro, declare o Box como <code>mut</code>:</p>

<pre><code class="language-rust">fn incrementa(n: &amp;mut i32) {

*n += 1;

}

fn main() {

let mut valor = Box::new(10);

incrementa(&amp;mut valor);

println!(&quot;{}&quot;, valor); // 11

}</code></pre>

<h2>Conclusão</h2>

<p>Box&lt;T&gt; é fundamental em Rust para alocação explícita no heap. Use-o para: (1) <strong>armazenar traits dinamicamente</strong> com <code>dyn</code>, eliminando dependências de tamanho em tempo de compilação; (2) <strong>criar estruturas recursivas</strong> quebrando ciclos de definição; (3) <strong>otimizar performance</strong> evitando cópias de dados grandes. Rust garante segurança de memória: quando o Box sai do escopo, seu conteúdo é automaticamente liberado.</p>

<h2>Referências</h2>

<ul>

<li><a href="https://doc.rust-lang.org/book/ch15-01-box.html" target="_blank" rel="noopener noreferrer">The Rust Book - Box&lt;T&gt;</a></li>

<li><a href="https://doc.rust-lang.org/std/boxed/struct.Box.html" target="_blank" rel="noopener noreferrer">Documentação Oficial: std::boxed::Box</a></li>

<li><a href="https://github.com/rust-lang/rustlings" target="_blank" rel="noopener noreferrer">Rustlings - Smart Pointers</a></li>

<li><a href="https://doc.rust-lang.org/rust-by-example/std/box.html" target="_blank" rel="noopener noreferrer">Rust by Example - Box and Deref</a></li>

<li><a href="https://www.oreilly.com/library/view/programming-rust/9781491927281/" target="_blank" rel="noopener noreferrer">Programming Rust - Jim Blandy &amp; Jason Orendorff</a></li>

</ul>

Comentários

Mais em Rust

Send e Sync em Rust: Segurança de Concorrência em Tempo de Compilação na Prática
Send e Sync em Rust: Segurança de Concorrência em Tempo de Compilação na Prática

Send: Transferência Segura Entre Threads é um trait que garante que um valor...

Dominando Macros em Rust: macro_rules! e Metaprogramação em Projetos Reais
Dominando Macros em Rust: macro_rules! e Metaprogramação em Projetos Reais

Introdução às Macros em Rust Macros são uma das características mais poderosa...

Guia Completo de Unsafe Rust: Quando e Como Usar com Responsabilidade
Guia Completo de Unsafe Rust: Quando e Como Usar com Responsabilidade

Entendendo Unsafe Rust Unsafe Rust é um subconjunto da linguagem que permite...