Cenários de Move-After-Use
Rust move valores em atribuições, chamadas de função e capturas de closure. Use referências, Clone ou tipos Copy quando precisar de múltiplos usos.
Receita
error[E0382]: use of moved value: `v`
Exemplo Funcional
// Antes
let v = vec![1, 2];
let w = v;
println!("{:?}", v); // erro
// Depois: emprestar (borrow)
let v = vec![1, 2];
let w = &v;
println!("{:?}", v);
// Depois: clonar (clone)
let v = vec![1, 2];
let w = v.clone();Fn consume:
fn take(s: String) {}
let name = String::from("Ada");
take(name);
// usar name novamente -> erro; clone antes de take se necessárioClosure move:
let data = vec![1];
let c = move || data.len(); // data movido para dentro do closureMergulho Profundo
Tipos Copy (inteiros, &T) duplicam em vez de mover. #[derive(Copy, Clone)] apenas quando todos os campos são Copy.
Armadilhas
- Move parcial de struct - outros campos ainda são válidos, a menos que a struct inteira seja movida.
- Consumo de iterador -
into_itermove os elementos. - Bloco
asyncmove - todas as variáveis de propriedade capturadas são movidas. Vec::removedurante iteração - useretainou itere os índices de trás para frente.- Esperar
CopyemString-Stringnão éCopy; clone explicitamente.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
argumento &T | Reutilização somente leitura | O callee precisa de propriedade |
Rc | Propriedade compartilhada | Mutação única sem RefCell |
Padrão take() | Troca de Option | Sempre Some |
FAQs
Move parcial?
Campo movido; acessar outros campos ok se não for struct parcialmente movida no mesmo padrão de vinculação com cuidado.
fn once?
FnOnce consome capturas; use Fn/FnMut para emprestar.
iterador vec?
for x in v move; use for x in &v para emprestar.
match move?
Vinculação por valor move; use ref no padrão ref x.
dica para erro E0382?
O rótulo mostra o local do move e o local do uso.
reutilizar em loop?
Recrie o valor de propriedade a cada iteração ou use referências.
envio de canal?
send move o valor para o canal.
retornar propriedade?
Mover para fora de uma fn é intencional; o chamador é o proprietário.
mem::replace?
Troca um placeholder enquanto constrói uma máquina de estados.
quando clone é barato?
Pequenas strings na fronteira; não em loop interno sem medição.
Relacionados
- Cenários de Erro do Borrow-Checker
- Semântica de Move
- Anti-Padrões Comuns
- Snippets de Refatoração para Debugging
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+.