Desafio Rust
Gerenciando múltiplos donos com move e clone
Enunciado
Você tem um Vec<String> com nomes. Crie uma função processa que recebe o vetor por valor, itera sobre ele e, para cada nome, imprime o nome e seu comprimento. A função deve consumir o vetor. No main, crie o vetor, faça um clone antes de chamar processa, e depois imprima o vetor original para provar que ele ainda está disponível.
Requisitos
- A função
processadeve receberVec<String>e retornar(). - O
maindeve clonar o vetor antes de passá-lo paraprocessa. - Após a chamada, o vetor original deve ser impresso com
{:?}. - A saída deve listar cada nome e seu tamanho, seguida do vetor original.
Código inicial
fn main() {
let nomes = vec![
String::from("Ana"),
String::from("Bruno"),
String::from("Carla"),
];
// clone, chame processa e imprima o original
}
fn processa(v: Vec<String>) {
// implemente
}
Saída esperada
Ana tem 3 letras
Bruno tem 5 letras
Carla tem 5 letras
Original: ["Ana", "Bruno", "Carla"]
Ver dica
Use nomes.clone() para criar uma cópia do vetor antes de mover. Dentro de processa, itere com for nome in v e use nome.len().
Mostrar solução
fn main() {
let nomes = vec![
String::from("Ana"),
String::from("Bruno"),
String::from("Carla"),
];
let copia = nomes.clone(); // cópia profunda do vetor e das strings
processa(copia); // move a cópia para a função
// nomes ainda é válido porque só a cópia foi movida
println!("Original: {:?}", nomes);
}
fn processa(v: Vec<String>) {
for nome in v { // consome o vetor, movendo cada String
println!("{} tem {} letras", nome, nome.len());
}
}
Passo a passo
vec![...]cria umVec<String>enomesse torna dona do vetor e das strings internas.nomes.clone()cria uma cópia profunda: um novo vetor com novasStrings clonadas.processa(copia)move a posse da cópia para o parâmetrov.- Dentro da função,
for nome in vconsome o vetor, movendo cadaStringparanomea cada iteração. - Cada
nomeé impresso com seu comprimento e depois liberado no fim da iteração. - Após a função,
copiafoi consumida, masnomespermanece intacto. - O
println!final imprime o vetor original.
Por que funciona
O clone cria uma cópia independente, então o move para processa não afeta nomes. O for sobre Vec<String> consome o vetor, movendo cada elemento; isso é seguro porque a função é dona do vetor. O ownership garante que não há aliasing mutável e que a memória é liberada corretamente.
Erros comuns
- Esquecer o
.clone()e passarnomesdiretamente:nomesseria movido e oprintln!final falharia comuse of moved value. - Tentar usar
copiaapósprocessa(copia): também seria um erro de move. - Iterar com
for nome in &vdentro deprocessa: funcionaria, mas não consumiria o vetor; o enunciado pede consumo.
Outra forma de resolver
Se não quiser clonar, passe uma referência imutável:
fn processa(v: &[String]) {
for nome in v {
println!("{} tem {} letras", nome, nome.len());
}
}
fn main() {
let nomes = vec![String::from("Ana"), String::from("Bruno"), String::from("Carla")];
processa(&nomes);
println!("Original: {:?}", nomes);
}
Essa é a forma idiomática quando não é necessário consumir o vetor.
Saída esperada
Ana tem 3 letras
Bruno tem 5 letras
Carla tem 5 letras
Original: ["Ana", "Bruno", "Carla"]