Empréstimos & Referências
Empréstimos permitem que o código use dados sem assumir a propriedade. Referências compartilhadas (&T) permitem leitores concorrentes. Referências mutáveis (&mut T) concedem acesso exclusivo de escrita.
Receita
fn push_char(s: &mut String, c: char) {
s.push(c);
}
fn display(s: &str) {
println!("{s}");
}
fn main() {
let mut msg = String::from("hi");
display(&msg);
push_char(&mut msg, '!');
display(&msg);
}Quando usar isso: APIs principalmente de leitura com &T, construtores e mutação com &mut T, evitando transferência de propriedade.
Exemplo de Trabalho
fn split_at_mut<T>(slice: &mut [T], mid: usize) -> (&mut [T], &mut [T]) {
slice.split_at_mut(mid)
}
fn main() {
let mut data = vec![1, 2, 3, 4];
let (left, right) = split_at_mut(&mut data, 2);
left[0] = 10;
right[0] = 40;
println!("{:?}", data);
}O que isso demonstra:
&mutexclusivo para mutaçãosplit_at_mutcria com segurança duas fatias&mutnão sobrepostas- O empréstimo termina quando
left/rightsaem do escopo &str/&[T]seguem as mesmas regras
Mergulho Profundo
Regras de Alias
- Qualquer número de
&Tou exatamente um&mut T - Referências devem sempre ser válidas (não pendentes)
- O escopo da referência termina no último uso (NLL) - veja página dedicada
Reemprestar
let mut s = String::from("a");
let r1 = &mut s;
let r2 = &*r1; // Reempresta compartilhado enquanto o empréstimo mutável está ativo em um subconjunto
println!("{r2}");Coerção &
&String -> &str, &Vec<T> -> &[T] via Deref.
Armadilhas
- Dois
&mutpara a mesma variável - Erro de compilação. Correção: Dividir escopos,split_at_mut, ou mutabilidade interior. - Leitura enquanto
&mutestá ativo - Proibido. Correção: Terminar o empréstimo mutável antes da leitura compartilhada. - Retornar
¶ dados locais - Referência pendente. Correção: Retornar valor de propriedade ou vincular o tempo de vida à entrada. - Empréstimo mutável entre chamadas de função que detêm
&mut- Estende o empréstimo. Correção: Limitar o escopo do empréstimo com blocos. - Iterar com coleção
&mutenquanto adiciona elementos - Invalidação do iterador. Correção: Coletar índices primeiro ou usardrain.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
| Parâmetro de propriedade | O chamador transfere o valor | Apenas leitura ou mutação curta |
RefCell/Mutex | Mutação compartilhada necessária | &mut exclusivo funciona |
| Índice + acesso bruto | Caminhos de alta performance inseguros | Abstrações seguras são suficientes |
| Canais | Passagem entre threads | Empréstimo na mesma thread funciona |
FAQs
Posso ter múltiplos `&mut` para campos diferentes?
Sim, com empréstimos de campos não sobrepostos: fn f(a: &mut S, b: &mut T) em campos diferentes via empréstimos divididos.
O que é uma referência pendente?
Uma referência que aponta para dados liberados ou movidos. Prevenido por tempos de vida e pelo verificador de empréstimos.
O `&mut` permite leitura?
Sim. &mut é acesso exclusivo de leitura/escrita.
Referências podem ser armazenadas em structs?
Sim, com parâmetros de tempo de vida: struct Holder<'a> { r: &'a str }.
E sobre `&'static`?
Empréstimo válido para todo o programa - literais de string, alocações vazadas, dados estáticos.
Como os empréstimos terminam?
No final do escopo ou último uso (tempos de vida não lexicais).
Closures podem emprestar?
Sim. Closures capturam por referência (&T, &mut T) ou por movimento.
São `&T` e `*const T` a mesma coisa?
Não. Referências são seguras, comprovadamente válidas. Ponteiros brutos precisam de unsafe para desreferenciar.
Empréstimos em braços de `match`?
Vinculações em match podem ser referências: match &mut v { ... }.
Como o empréstimo interage com `async`?
&mut mantido através de .await é frequentemente rejeitado. Use estado de propriedade ou Mutex em async.
Relacionado
- O Verificador de Empréstimos - raciocínio do compilador
- Tempos de Vida Explicados - por que
'aexiste - Tempos de Vida Não Lexicais e Reemprestos - comportamento moderno
- Referências e Fatias - noções básicas de fatias
Versões da Pilha: Esta página foi escrita para Rust 1.97.0 (edição 2024), Tokio 1.x, Axum 0.8, serde 1.0, sqlx 0.8, clap 4, e Polars 0.46+.