Lição: 006: Propriedade e Empréstimo em Rust
Nesta aula, vamos abordar dois conceitos fundamentais do Rust: Propriedade e Empréstimo. Compreender esses conceitos é essencial para escrever programas seguros e eficientes em Rust.
Propriedade
Em Rust, a propriedade é um conjunto de regras que rege como a memória é gerenciada. Cada pedaço de dados tem um único proprietário, que é responsável por limpar os dados quando eles saem do escopo.
Regras de Propriedade
- Cada valor em Rust possui uma variável que é seu "proprietário".
- Um valor pode ter apenas um proprietário por vez.
- Quando o proprietário de um valor sai do escopo, Rust irá automaticamente limpar o valor.
Exemplo de Propriedade
fn main() {
let s1 = String::from("Olá, Rust!"); // s1 é o proprietário da String
println!("{}", s1); // Podemos usar s1
let s2 = s1; // A propriedade é movida de s1 para s2
// println!("{}", s1); // Esta linha causaria um erro em tempo de compilação
println!("{}", s2); // s2 é o proprietário agora
}
No exemplo acima, s1
é o proprietário de uma String
. Quando atribuimos s1
a s2
, a propriedade é transferida para s2
; assim, s1
não é mais válido.
Empréstimo
Empréstimo permite que você use um valor sem tomar a propriedade dele. O empréstimo pode ser mutável ou imutável:
- Empréstimo imutável: Você pode ter várias referências imutáveis a um valor, mas não pode ter referências mutáveis ao mesmo tempo.
- Empréstimo mutável: Você pode ter uma referência mutável a um valor, mas não pode ter referências imutáveis ao mesmo tempo durante o empréstimo mutável.
Exemplo de Empréstimo
fn main() {
let s = String::from("Olá, Empréstimo!");
let len = calcular_comprimento(&s); // Empréstimo de s
println!("O comprimento de '{}' é {}.", s, len);
}
fn calcular_comprimento(s: &String) -> usize { // s é uma referência
s.len() // Podemos usar s aqui, mas não somos proprietários dela
}
Neste exemplo, passamos uma referência para a função calcular_comprimento
em vez de tomar a propriedade de s
. A função pode ler s
, mas não pode modificá-la ou possuir.
Empréstimo Mutável
fn main() {
let mut s = String::from("Olá, empréstimo mutável!");
alterar(&mut s); // Empréstimo mutável
println!("{}", s);
}
fn alterar(s: &mut String) {
s.push_str(" Foi alterado!"); // Podemos modificar s
}
Aqui, criamos uma string mutável e passamos uma referência mutável para a função alterar
. Dentro da função, adicionamos uma nova string a s
. Como s
foi emprestada de forma mutável, garantimos que não existam outras referências a ela durante esse tempo.
Verificações em Tempo de Compilação
As regras de propriedade e empréstimo do Rust são aplicadas em tempo de compilação, o que ajuda a eliminar muitos erros comuns causados por ponteiros soltos ou condições de corrida. Se você tentar violar as regras de empréstimo, o compilador Rust gerará um erro, ajudando você a identificar problemas antes da execução.
Exemplo de Violação das Regras de Empréstimo
fn main() {
let mut s = String::from("Olá, Rust!");
let r1 = &s; // Empréstimo imutável
let r2 = &s; // Outro empréstimo imutável
// let r3 = &mut s; // Esta linha geraria um erro em tempo de compilação
println!("{} e {}", r1, r2);
}
O código acima gera um erro porque não podemos ter um empréstimo mutável (r3
) enquanto empréstimos imutáveis (r1
e r2
) ainda estão ativos.
Conclusão
Propriedade e empréstimo são partes integrais da linguagem de programação Rust, promovendo segurança de memória sem um coletor de lixo. Dominar esses conceitos fará de você um desenvolvedor Rust mais eficaz, permitindo que você escreva programas seguros e eficientes.
Nesta aula, introduzimos os conceitos de propriedade e empréstimo, esclarecemos a diferença entre referências mutáveis e imutáveis, e destacamos as verificações em tempo de compilação impostas pelo Rust. Continue experimentando com esses conceitos para se tornar proficiente neles!