Pular para o conteúdo principal
Módulo 6 · Lição 1 de 211/14 no curso~15 min
Lições do módulo (1/2)

Vidas e referências

No Rust, toda referência tem um tempo de vida, que corresponde ao escopo dentro do qual aquela referência é válida. Na maioria das vezes, os tempos de vida são implícitos e inferidos pelo compilador graças às regras de elisão de tempo de vida. Contudo, quando a relação entre os tempos de vida de diferentes referências é ambígua, devemos anotá-las explicitamente.

O principal objetivo dos tempos de vida é evitar referências pendentes (referências a dados que já foram desalocados da memória).


Sintaxe de anotação vitalícia

Os nomes vitalícios começam com um apóstrofo (') e geralmente são letras minúsculas curtas (como 'a). As anotações de tempo de vida não alteram o tempo de vida real das variáveis, mas indicam ao compilador a relação entre a validade das entradas e das saídas.

Por exemplo, se uma função recebe dois parâmetros de referência de string e retorna uma referência de string, e queremos que a referência retornada seja válida desde que ambos os parâmetros de entrada sejam válidos, usamos:

Rust
fn longest<'a>(x: &'a str, y: &'a str) -> &'a str {
    if x.len() > y.len() {
        x
    } else {
        y
    }
}

Vidas em estruturas de dados

Se uma estrutura contém um campo que é uma referência, devemos anotar explicitamente o tempo de vida dessa referência para garantir que a instância da struct não possa sobreviver aos dados aos quais se refere:

Rust
struct ImportantExcerpt<'a> {
    part: &'a str,
}

fn main() {
    let novel = String::from("Call me Ishmael. Some years ago...");
    let first_sentence = novel.split('.').next().unwrap();
    let i = ImportantExcerpt {
        part: first_sentence,
    };
}

A vida estática

A vida útil 'static é uma vida útil especial que dura toda a duração do programa. Todos os literais de string (&str) têm implicitamente um tempo de vida 'static porque são armazenados diretamente dentro do executável binário.

Rust
let s: &'static str = "I have a static lifetime.";

Experimente você mesmo

Exercício 1: A função mais longa

Exercício#rust.m6.l1.e1
Tentativas: 0Carregando…

Escreva uma função chamada mais longa<'a> que aceita dois parâmetros, x do tipo &'a str e y do tipo &'a str, e retorna um valor do tipo &'a str. Dentro da função, use um bloco if/else para retornar x se seu comprimento for maior que y, caso contrário, retorne y.

Carregando editor…
Mostrar dica

Declare a assinatura com `fn mais longo<'a>(x: &'a str, y: &'a str) -> &'a str`. Então use `if x.len() > y.len() { x } else { y }`.

Solução disponível após 3 tentativas

Exercício 2: Estruturas com Referências

Exercício#rust.m6.l1.e2
Tentativas: 0Carregando…

Defina uma estrutura chamada Excerpt<'a> contendo um único campo chamado parte do tipo &'a str. Na função principal, crie uma variável de string chamada text e instancie um trecho de variável do tipo Excerpt pegando emprestada uma referência ao texto. Imprimir trecho.parte.

Carregando editor…
Mostrar dica

Use `struct Excerpt<'a> { parte: &'a str }`. Em main, instancie-o com `Excerpt {part: &text }`.

Solução disponível após 3 tentativas

Exercício 3: Referências Estáticas

Exercício#rust.m6.l1.e3
Tentativas: 0Carregando…

Declare uma variável chamada message com uma anotação de tipo explícita para o tempo de vida estático (&'static str), atribuindo a ela uma string literal. Imprima o valor da mensagem.

Carregando editor…
Mostrar dica

Use a sintaxe `let message: &'static str = 'Messaggio statico!';` para anotar explicitamente o tempo de vida estático.

Solução disponível após 3 tentativas