Rust propose deux façons d'implémenter un tableau de caractères : str et String.
str, aussi appelé « tranche de string », s'utilise généralement par référence, sous la forme &str.
Pour comprendre pourquoi, il peut être utile de savoir pourquoi la ligne de code suivante ne compile pas
const MY_CONST: str = *"Hello, World!";
// the size for values of type `str` cannot be known at compilation time
// the trait `Sized` is not implemented for `str`
Même si la longueur du littéral « Hello, World! » peut être connue au moment de la compilation, en tant que str, c'est une séquence dont la taille est inconnue.
Mais en tant que référence vers un littéral (&str), il possède un « pointeur épais » qui contient l'adresse et la longueur du littéral en mémoire.
Les pointeurs épais ont une taille connue, et cette ligne compilera donc
const MY_CONST: &str = "Hello, World!";
Une liaison mutable vers une tranche de string peut voir sa valeur remplacée, mais pas modifiée sur place.
Exemple
let mut my_str = "Hello, World!";
my_str = "Hi!";
let mut my_string = String::from("Hello");
my_string.push_str(", World!"); // there is no equivalent function to modify &str
Il est moins contraignant d'utiliser &str plutôt que &String lorsqu'on définit le paramètre d'une fonction, car ceci ne compilera pas
pub fn main() {
let my_str: &str = "Hello, World!";
say_hi(my_str);
}
fn say_hi(phrase: &String) {
println!("{phrase:?}");
}
// mismatched types
// expected reference `&String`
// found reference `&str`
Un &str ne sera pas converti en &String. Mais ceci compilera
pub fn main() {
let my_string = String::from("Hello, World!");
say_hi(&my_string)
}
fn say_hi(phrase: &str) {
println!("{phrase:?}");
}
Un &String sera converti en &str. Utiliser un paramètre de type &str sera donc souvent plus utile.