Les durades de vida (lifetimes) són un concepte fonamental en Rust que ajuda a garantir la seguretat de la memòria. En aquest tema, explorarem què són les durades de vida, com es declaren i com es poden utilitzar per evitar errors comuns relacionats amb la memòria.
Què són les Durades de Vida?
Les durades de vida són anotacions que el compilador de Rust utilitza per assegurar-se que totes les referències són vàlides. En altres paraules, les durades de vida defineixen l'abast durant el qual una referència és vàlida.
Exemple Bàsic
Considerem el següent codi:
Aquest codi no compilarà perquè x
no viu prou temps per satisfer la referència r
. El compilador de Rust detecta aquest problema i genera un error.
Anotacions de Durades de Vida
Les anotacions de durades de vida es declaren amb un apòstrof ('
) seguit d'un nom. Per exemple, 'a
és una anotació de durada de vida. Aquestes anotacions no canvien el temps d'execució del codi; només ajuden el compilador a verificar la validesa de les referències.
Sintaxi
En aquest exemple, 'a
és una anotació de durada de vida que indica que la referència input
i el valor retornat tenen la mateixa durada de vida.
Regles de Durades de Vida
Rust té algunes regles implícites per inferir les durades de vida, però en alguns casos, cal especificar-les explícitament.
Primera Regla
Cada referència en els paràmetres d'una funció obté la seva pròpia durada de vida.
Segona Regla
Si hi ha exactament una referència d'entrada, aquesta durada de vida s'assigna a totes les referències de sortida.
Tercera Regla
Si hi ha múltiples referències d'entrada, però una d'elles és &self
o &mut self
, la durada de vida de self
s'assigna a totes les referències de sortida.
Exemples Pràctics
Exemple 1: Funció amb una Referència
En aquest exemple, la funció longest
pren dues referències de cadena amb la mateixa durada de vida 'a
i retorna una referència amb la mateixa durada de vida.
Exemple 2: Estructura amb Durades de Vida
struct ImportantExcerpt<'a> { part: &'a str, } fn main() { let novel = String::from("Call me Ishmael. Some years ago..."); let first_sentence = novel.split('.').next().expect("Could not find a '.'"); let i = ImportantExcerpt { part: first_sentence, }; }
En aquest exemple, l'estructura ImportantExcerpt
conté una referència amb una durada de vida 'a
. Això assegura que la referència part
dins de l'estructura és vàlida mentre ho sigui la cadena original.
Exercicis Pràctics
Exercici 1
Escriu una funció shortest
que prengui dues referències de cadena i retorni la més curta. Assegura't d'utilitzar anotacions de durades de vida.
Solució
Exercici 2
Crea una estructura Book
que contingui una referència a una cadena title
. Implementa una funció que retorni el títol del llibre.
struct Book<'a> { title: &'a str, } impl<'a> Book<'a> { fn get_title(&self) -> &'a str { // Implementa la funció aquí } }
Solució
struct Book<'a> { title: &'a str, } impl<'a> Book<'a> { fn get_title(&self) -> &'a str { self.title } }
Errors Comuns i Consells
- Error: Referència no vàlida: Assegura't que les referències no surtin del seu abast.
- Error: Durades de vida no especificades: Si el compilador no pot inferir les durades de vida, especifica-les explícitament.
- Consell: Utilitza les regles implícites de durades de vida per simplificar el codi quan sigui possible.
Resum
En aquesta secció, hem après què són les durades de vida, com es declaren i com es poden utilitzar per assegurar la seguretat de la memòria en Rust. Hem vist exemples pràctics i hem practicat amb exercicis per reforçar els conceptes apresos. Les durades de vida són una eina poderosa que ajuda a Rust a garantir la seguretat de la memòria sense necessitat d'un recollidor d'escombraries (garbage collector).