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-
Copymove 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 comoString.dropé chamado automaticamente no fim do escopo e pode ser forçado comstd::mem::drop.
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
}