Da trilha de Rust Este conceito ainda não saiu como card do dia. ir para o card de hoje

Rust Memória Básico

Ownership

Em Rust, ownership (propriedade) é o sistema que garante segurança de memória sem garbage collector. Cada valor tem um único dono, e quando o dono sai de escopo, o valor é liberado automaticamente (chamada de drop). Isso evita use-after-free e double free em tempo de compilação.

Quando você atribui um valor a outra variável ou passa para uma função, a propriedade pode ser movida (move). Após o move, a variável original não pode mais ser usada. Tipos que implementam Copy (como inteiros e booleanos) são copiados automaticamente, então continuam válidos após a atribuição.

Para tipos que não são Copy (como String), você pode usar .clone() para criar uma cópia profunda explícita. O drop é chamado automaticamente no fim do escopo, mas também pode ser forçado com std::mem::drop.

Entender essas regras é essencial para escrever código Rust idiomático e evitar erros de compilação como borrow of moved value.

Pontos-chave

  • Cada valor tem um único dono; quando o dono sai de escopo, o valor é liberado.
  • Atribuir ou passar um valor não-Copy move a propriedade; a variável original fica inválida.
  • Tipos Copy (inteiros, floats, bool, char) são copiados, não movidos.
  • .clone() cria uma cópia explícita e profunda para tipos como String.
  • drop é chamado automaticamente no fim do escopo e pode ser forçado com std::mem::drop.
ownership.rs
fn main() {
    // String não é Copy: atribuição move a propriedade
    let s1 = String::from("olá");
    let s2 = s1; // s1 foi movido para s2
    // println!("{}", s1); // ERRO: s1 não é mais válido
    println!("s2 = {}", s2);

    // Tipos Copy são copiados, não movidos
    let x = 5;
    let y = x; // x continua válido
    println!("x = {}, y = {}", x, y);

    // Clone explícito para copiar String
    let s3 = String::from("mundo");
    let s4 = s3.clone();
    println!("s3 = {}, s4 = {}", s3, s4);

    // Passar para função move a propriedade
    let s5 = String::from("Rust");
    let len = calcula_tamanho(s5); // s5 movido
    // println!("{}", s5); // ERRO
    println!("Tamanho: {}", len);

    // drop forçado
    let s6 = String::from("descartar");
    drop(s6); // libera s6 agora
    // println!("{}", s6); // ERRO
}

fn calcula_tamanho(s: String) -> usize {
    s.len() // s é dono do valor e o libera ao final
}

Exercícios

  1. 1
    Fácil

    Corrigindo move de String

    O código abaixo tenta usar s1 depois de mover seu valor para s2. Corrija-o para que compile sem erros, mantendo ambas as variáveis válidas. Use .clone() para criar uma cópia independente.

    Resolver
  2. 2
    Médio

    Função que consome e devolve

    Crie uma função adiciona_ponto que recebe uma String por valor, adiciona um ponto final e devolve a String modificada. No main, chame a função passando uma string, imprima o resultado e garanta que a variável original não seja usada após a chamada (pois foi movida).

    Resolver
  3. 3
    Desafio

    Gerenciando múltiplos donos com move e clone

    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.

    Resolver

Continue estudando