Noções Básicas de Propriedade
10 exemplos para você começar com propriedade - 7 básicos e 3 intermediários.
Pré-requisitos
- Noções Básicas de Rust - variáveis e funções
- Preview de Propriedade - primeira olhada em moves
Exemplos Básicos
1. Regra do Proprietário Único
fn main() {
let s = String::from("owner");
consume(s);
// println!("{s}"); // erro: movido
}
fn consume(s: String) {
println!("{s}");
}Stringpossui bytes no heap- Passar
sparaconsumemove a propriedade - Após um move, a ligação original não pode ser usada
consumedescarta (drops)sno final do escopo
Relacionado: Semântica de Move e Cópia - tipos
Copy
2. Escopo e Drop
fn main() {
{
let s = String::from("temp");
println!("{s}");
} // drop é executado aqui
println!("done");
}- Proprietários saem do escopo no final do bloco
Drop::droplibera recursos (heap paraString)- Sem GC - limpeza determinística
- Ordem: o último criado, o primeiro descartado (desenrolamento da pilha)
Relacionado: Noções Básicas de Ponteiros Inteligentes -
Droppersonalizado
3. Move Entre Variáveis
fn main() {
let a = vec![1, 2, 3];
let b = a;
println!("{:?}", b);
}Vecnão éCopy- A atribuição move, não duplica bit a bit
- Apenas uma ligação possui a alocação
- Move barato: copia ponteiro/tamanho/capacidade na pilha
4. Retorno de Função Transfere Propriedade
fn make_greeting() -> String {
String::from("hello")
}
fn main() {
let g = make_greeting();
println!("{g}");
}- O chamador se torna o proprietário do valor retornado
- O retorno é um move (ou cópia de valor de pilha elidida por NRVO)
- A propriedade pode fluir para dentro e para fora das funções
- Retorne
Stringquando o chamador deve possuir os dados
5. Move Parcial de Structs
struct Pair { a: String, b: String }
fn main() {
let p = Pair { a: "x".into(), b: "y".into() };
let a = p.a; // move parcial
// println!("{}", p.b); // OK
println!("{a}");
}- Mover um campo não move a struct inteira se outros campos permanecerem
- A struct inteira é movida se todos os campos forem movidos ou se a struct for
Copy - Projete structs para minimizar confusão de move parcial
- Prefira emprestar (
borrowing) campos quando possível
6. Empréstimo Evita Move
fn len(s: &String) -> usize { s.len() }
fn main() {
let s = String::from("rust");
println!("{}", len(&s));
println!("ainda possuo: {s}");
}&Stringempresta sem tirar a propriedade- O proprietário permanece válido após o fim do empréstimo
- Muitas APIs somente leitura devem aceitar referências
- Veja a seção de Empréstimo (
Borrowing) para&mut
Relacionado: Empréstimo e Referências
7. Propriedade com Crescimento de Vec
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
let last = v.pop().unwrap();
println!("{last}, len={}", v.len());
}Vecpossui um buffer no heappushpode realocar e mover elementospopremove a propriedade do último elemento para o chamador- Iteradores podem emprestar elementos sem mover o
Vec
Exemplos Intermediários
8. Drop Personalizado com Efeitos Colaterais
struct LogOnDrop(&'static str);
impl Drop for LogOnDrop {
fn drop(&mut self) {
println!("dropping {}", self.0);
}
}
fn main() {
let _x = LogOnDrop("resource");
}- Implemente
Droppara limpeza além da memória dropé chamado automaticamente, não recursivamente pelo valorstd::mem::drop(x)executa odropantecipadamente explicitamente- Não chame
Drop::dropmanualmente em valores
9. Rc para Propriedade Compartilhada (Preview)
use std::rc::Rc;
fn main() {
let a = Rc::new(String::from("shared"));
let b = Rc::clone(&a);
println!("refs={}", Rc::strong_count(&a));
drop(b);
println!("{a}");
}Rcconta os proprietários em código single-threadedRc::cloneincrementa a contagem, não faz clone profundo da string- O valor é descartado quando a contagem chega a zero
Arcé a variante thread-safe
Relacionado: Rc & Arc
10. Propriedade em Coleções
fn main() {
let mut map = std::collections::HashMap::new();
map.insert("key".to_string(), vec![1, 2]);
if let Some(v) = map.remove("key") {
println!("{:?}", v);
}
}HashMappossui chaves e valoresinsertmove o valor para dentroremovemove o valor para fora (deixa a chave ausente)- Empreste com
getpara consulta somente leitura
Relacionado: Melhores Práticas de Propriedade
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+.