Rust Memória Intermediário
Lifetimes
Em Rust, lifetimes são uma forma de o compilador garantir que referências não durem mais que os dados que elas apontam. Eles não mudam o tempo de vida real das variáveis; servem para anotar e verificar relacionamentos entre referências. A sintaxe usa apóstrofo ('a) e aparece em funções, structs e métodos.
O compilador aplica elisão de lifetimes em casos comuns, como funções com um único parâmetro de referência ou métodos com &self. Quando há ambiguidade, precisamos anotar explicitamente. Em structs que guardam referências, é obrigatório declarar um parâmetro de lifetime, como struct Fatia<'a> { dados: &'a str }.
O lifetime especial 'static indica que a referência pode viver por toda a execução do programa. É o caso de literais string (&'static str) e de dados alocados globalmente. Usar 'static em excesso pode indicar design rígido, mas é útil para constantes e configurações.
Entender lifetimes é essencial para escrever funções genéricas seguras e structs que emprestam dados sem copiar. Com a prática, você percebe que a maioria das anotações segue padrões simples e que o compilador geralmente consegue inferir o resto.
Pontos-chave
- Lifetimes são anotações que descrevem por quanto tempo uma referência é válida.
- A elisão permite omitir lifetimes em funções com um único parâmetro de referência ou métodos com
&self. - Structs que armazenam referências precisam declarar um parâmetro de lifetime, como
struct S<'a> { x: &'a T }. 'staticindica que a referência vive por toda a execução do programa.- O compilador usa lifetimes para impedir referências pendentes em tempo de compilação.
// Exemplo de lifetimes em funções, structs e 'static
// Função que retorna a referência mais longa entre duas strings.
// O lifetime 'a garante que o retorno vive pelo menos tanto quanto os argumentos.
fn mais_longa<'a>(x: &'a str, y: &'a str) -> &'a str {
if x.len() > y.len() { x } else { y }
}
// Struct que guarda uma referência: precisa de lifetime explícito.
struct Trecho<'a> {
texto: &'a str,
}
impl<'a> Trecho<'a> {
// Método que retorna uma referência com o mesmo lifetime da struct.
fn primeiro(&self) -> &'a str {
&self.texto[..1]
}
}
// Função que aceita apenas referências estáticas.
fn imprime_estatico(s: &'static str) {
println!("Estático: {}", s);
}
fn main() {
let a = String::from("curto");
let b = String::from("muito mais longo");
let resultado = mais_longa(&a, &b);
println!("Mais longa: {}", resultado);
let t = Trecho { texto: "exemplo" };
println!("Primeiro caractere: {}", t.primeiro());
imprime_estatico("literal global");
}