Pular para conteúdo

Aula 06 - Borrowing e Referências 🤝

Objetivo

Objetivo: Aprender a acessar dados sem obter sua posse (Ownership) através do conceito de Referências e Empréstimo (Borrowing).


1. O que são Referências? 🔍

Uma referência é como um ponteiro, mas com a garantia de que sempre apontará para um valor válido. Usamos o símbolo & para referenciar.

fn main() {
    let s1 = String::from("texto");
    let tam = calcular_tamanho(&s1); // Passamos uma referência, não a posse
    println!("O tamanho de '{}' é {}.", s1, tam); // s1 ainda é válido!
}

fn calcular_tamanho(s: &String) -> usize {
    s.len()
} // s sai de escopo, mas como é uma referência, nada é descartado na Heap.

2. Empréstimo Mutável ✍️

Por padrão, referências são imutáveis. Para mudar um valor emprestado, precisamos de uma referência mutável (&mut).

fn main() {
    let mut s = String::from("olá");
    mudar(&mut s);
}

fn mudar(valor: &mut String) {
    valor.push_str(", mundo");
}

3. As Regras do Borrow Checker ⚖️

O Rust impõe duas regras fundamentais para evitar corridas de dados (data races):

  1. Você pode ter várias referências imutáveis (&T) ao mesmo tempo.
  2. Você pode ter apenas uma referência mutável (&mut T) por vez.
  3. Você não pode ter uma referência mutável se já houver uma imutável ativa.
let mut s = String::from("oi");

let r1 = &s; // OK
let r2 = &s; // OK
// let r3 = &mut s; // ERRO de compilação! (Já existem referências imutáveis)

4. Referências Pendentes (Dangling References) 🪢

O Rust impede que você crie referências que apontem para memória que já foi liberada.

// ERRO: s sai de escopo e é destruída, mas tentamos retornar uma referência a ela.
// fn dangling() -> &String {
//    let s = String::from("oi");
//    &s 
// }

5. Visualização: Referências em Memória 🖼️

graph LR
    subgraph Stack
        r1[r1: &String]
    end
    subgraph Heap
        Data[("String: 'texto'")]
    end
    r1 --> s1[s1: dono da String]
    s1 --> Data
    style r1 fill:#bbf,stroke:#333

6. Mini-Projeto: Editor de Texto Simples 📄

Crie um programa que: 1. Tenha uma String principal representando um documento. 2. Uma função exibir que recebe uma referência imutável e imprime o texto. 3. Uma função editar que recebe uma referência mutável e adiciona uma linha ao documento. 4. Tente (e veja falhar) chamar editar enquanto uma referência de exibir ainda estiver sendo usada.


7. Exercício de Fixação 🧠

Atenção

O escopo de uma referência começa onde ela é introduzida e termina na sua última utilização.

  1. Qual a diferença entre &String e String em termos de Ownership?
  2. Por que o Rust proíbe ter duas referências mutáveis ao mesmo tempo?
  3. Como o compilador sabe que uma referência é "pendente"?

Próxima Aula: Vamos trabalhar com textos e conjuntos de dados em Strings e Coleções! 🧵