ProgrammationDéveloppeur Fullstack

Comment fonctionne le traitement des chaînes immuables et du type dynamique String en Rust ? Quelles sont les différences entre String et &str, comment fonctionne la propriété, et comment convertir en toute sécurité entre ces types ?

Réussissez les entretiens avec l'assistant IA Hintsage

Réponse.

Historique de la question :

Comparé aux langages natifs (C/C++), Rust construit un traitement sûr des chaînes grâce à une distinction stricte entre les types de référence (&str) et de propriété (String). Cela élimine la plupart des erreurs liées à la gestion incorrecte de la mémoire, aux dépassements de tampon et aux double-free.

Problème :

Contrairement aux langages avec GC plus conviviaux, où chaque chaîne vit dans une mémoire gérée, en Rust, il est essentiel de comprendre qui possède la chaîne, combien de temps elle vit et comment éviter les références pendantes après des modifications. Travailler avec des chaînes UTF-8 nécessite de la prudence lors de l'indexation et de la modification.

Solution :

En Rust, String est une chaîne mutable, allouée sur le tas, qui possède son contenu. &str est une référence immuable à une séquence d'octets avec la garantie UTF-8. Il est possible de convertir en toute sécurité (&str -> String et vice versa) à l'aide des méthodes std.

Exemple de code :

fn main() { let owned: String = String::from("Rust"); let borrowed: &str = &owned; let primitive: &str = "Hello"; // le littéral est toujours &str // Conversion &str -> String let s: String = primitive.to_string(); // Conversion String -> &str let st: &str = &s; println!("{} {} {} {}", owned, borrowed, primitive, st); }

Caractéristiques clés :

  • Distinction explicite entre la propriété et la référence (tas vs tranche)
  • Les méthodes de conversion sécurisées entre String et &str sont efficaces et transparentes en termes de durée de vie de l'objet
  • Les littéraux de chaîne ont toujours le type &'static str, et non String

Questions pièges.

Pourquoi ne peut-on pas indexer une chaîne comme s[1] ou s[i] ?

Les chaînes Rust sont en UTF-8, donc l'indexation n'est pas accessible directement : s[i] ne renvoie pas le i-ème caractère et peut parfois provoquer un panic lors de l'accès à une limite de byte incorrecte. Utilisez plutôt les méthodes .chars().nth(i) ou .get(start..end).

Peut-on modifier un &str de manière sécurisée ?

Non - &str est toujours un slice immuable. Pour les modifications, utilisez to_owned/to_string, ou bien employez String/Vec<u8>.

Quelle est la différence fondamentale entre String::from("abc") et "abc".to_string() ?

Ces deux options sont équivalentes en termes de résultat, elles créent toutes deux une String en copiant les données depuis &str. La différence réside uniquement dans le style : par exemple, to_string est implémenté via le trait ToString, tandis que String::from exprime plus clairement l'intention "créer une propriété".

Erreurs typiques et anti-patterns

  • Essayer d'indexer une chaîne s[1] ou s[0] pour obtenir char
  • Conversions implicites sans spécification de durée de vie : retour de références vers des objets temporaires
  • Utilisation de String là où un &str est suffisant (allocation superflue)

Exemple de la vie réelle

Cas négatif

La fonction prenait String et effectuait une copie inutile de la chaîne à l'intérieur (clone), puis écrivait un slice dans une autre fonction, oubliant de prolonger la durée de vie de la source. Résultat : référence pendante & crash.

Avantages :

  • Similaire aux langages familiers : on peut facilement obtenir une "copie" de la chaîne

Inconvénients :

  • Pertes de performance en raison des allocations superflues
  • Risque de fuite de références vers des valeurs temporaires

Cas positif

La fonction accepte &str, et si des modifications sont nécessaires, elle appelle .to_string() à l'intérieur, tandis que toute la logique à l'extérieur reste sans copie. Les durées de vie sont sous contrôle, aucune allocation superflue.

Avantages :

  • Haute performance
  • Problèmes de propriété évités

Inconvénients :

  • Nécessité de comprendre les durées de vie et la propriété
  • Une charge cognitive légèrement plus importante pour les débutants