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):
- Você pode ter várias referências imutáveis (
&T) ao mesmo tempo. - Você pode ter apenas uma referência mutável (
&mut T) por vez. - 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.
- Qual a diferença entre
&StringeStringem termos de Ownership? - Por que o Rust proíbe ter duas referências mutáveis ao mesmo tempo?
- 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! 🧵