English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
Le mécanisme de durée de vie de Rust est un mécanisme de gestion des ressources aussi important que le mécanisme d'appartenance.
Cette notion a été introduite principalement pour faire face aux problèmes de gestion des ressources dans les systèmes de types complexes.
Les références sont un mécanisme indispensable pour traiter les types complexes, car les données de types complexes ne peuvent pas être copiées ou calculées facilement par les processeurs.
Mais l'utilisation fréquente conduit souvent à des problèmes de gestion des ressources extrêmement complexes, voici donc une introduction à ce qu'on appelle les références suspendues :
{ let r; { let x = 5; r = &x; } println!("r: {}", r); }
Ce code ne peut pas être compilé par le compilateur Rust, car la valeur que r référence a été libérée avant son utilisation.
La gamme verte 'a dans l'image représente la durée de vie de r, la gamme bleue 'b représente la durée de vie de x. Il est évident que 'b est beaucoup plus petite que 'a, la référence doit être dans la durée de vie de la valeur pour être valide.
Nous avons toujours utilisé String dans la structure au lieu de &str, nous expliquons la raison avec un exemple :
fn longer(s1: &'str, s2: &'str) -> &str { if s2.len() > s1.len() { s2 else { s1 } }
La fonction longer prend s1 et s2 Le plus long des deux tronçons de chaîne de caractères renvoie sa valeur de référence. Mais ce seul code ne peut pas être compilé, car la valeur de retour de la référence peut renvoyer une référence périmée :
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); } println!("{} est plus long", r); }
Dans ce programme, bien que comparé, mais r est utilisé lorsque la valeur source s1 et s2 ont tous deux été invalidés. Bien sûr, nous pouvons déplacer l'utilisation de r vers s1 et s2 dans la gamme de la durée de vie pour éviter de telles erreurs, mais pour une fonction, elle ne peut pas savoir ce qui se passe en dehors d'elle, pour garantir que les valeurs qu'elle transmet sont normales, elle doit éliminer tous les dangers par le principe de propriété, donc la fonction longer ne peut pas être compilée.
Les annotations de durée de vie sont une méthode pour décrire la durée de vie des références.
Bien que cela ne puisse pas changer la durée de vie de la référence, cela permet de déclarer que les deux références ont une durée de vie identique à un endroit approprié.
Les annotations de durée de vie commencent par un guillemet simple suivi d'un mot en minuscule :
&i32 // Référence conventionnelle &'a i32 // Référence avec annotation de durée de vie &'a mut i32 // Référence mutable avec annotation de durée de vie
Transformons la fonction longer en utilisant des annotations de durée de vie :
fn longer<'a>(s1: &'a str, s2: &'a str) -> &'a str { if s2.len() > s1.len() { s2 else { s1 } }
Nous devons utiliser une déclaration générique pour normaliser le nom de la durée de vie, puis la durée de vie de la valeur de retour de la fonction sera identique à celle des deux paramètres, donc nous pouvons écrire ainsi lors de l'appel :
fn main() { let r; { let s1 = "rust"; let s2 = "ecmascript"; r = longer(s1, s2); println!("{} est plus long", r); } }
Résultat de l'exécution combinée des deux derniers paragraphes de programme :
ecmascript est plus long
Attention :N'oubliez pas le principe de jugement de type automatique.
C'est la question laissée précédemment, voici la réponse :
fn main() { struct Str<'a> {}} content: &'a str } let s = Str { content: "string_slice" }; println!("s.content = {}", s.content); }
Résultat de l'exécution :
s.content = string_slice
Si vous définissez une méthode pour la structure Str :
impl<'a> Str<'a> { fn get_content(&self) -> &str { self.content } }
Le retour de la valeur n'a pas d'annotation de cycle de vie, mais cela ne fait pas de mal. C'est un problème historique, car les versions initiales de Rust ne prenaient pas en charge l'auto-détection des cycles de vie, tous les cycles de vie devaient être déclarés strictement, mais les versions stables principales de Rust prennent désormais en charge cette fonctionnalité.
Il y a une annotation spéciale pour les annotations de cycle de vie : 'static. Tous les types de données spécifiques représentés par les chaînes constantes encadrées par des guillemets doubles sont &'static str, le cycle de vie de 'static commence au début de l'exécution du programme et se termine à la fin de l'exécution du programme.
use std::fmt::Display; fn longest_with_an_announcement<'a, T>(x: &'a str, y: &'a str, ann: T) -> &'a str where T: Display { println!("Annonce ! {}", ann); if x.len() > y.len() { x else { y } }
Ce programme provient du Bible Rust, il utilise à la fois les mécanismes de genericité, de traits et de cycle de vie, il n'est pas obligatoire, vous pouvez l'essayer, car il sera certainement utilisé à un moment donné !