TL; DR: On peut utiliser à la place &str, &[T]ou &Tpour permettre un code plus générique.
L'une des principales raisons d'utiliser a Stringou a Vecest qu'ils permettent d'augmenter ou de diminuer la capacité. Cependant, lorsque vous acceptez une référence immuable, vous ne pouvez utiliser aucune de ces méthodes intéressantes sur le Vecfichier ou String.
L'acceptation d'un &String, &Vecou nécessite&Box également que l'argument soit alloué sur le tas avant de pouvoir appeler la fonction. L'acceptation de a &strautorise un littéral de chaîne (enregistré dans les données du programme) et l'acceptation de &[T]ou &Tautorise un tableau ou une variable alloué à la pile. Une allocation inutile est une perte de performance. Ceci est généralement exposé immédiatement lorsque vous essayez d'appeler ces méthodes dans un test ou une mainméthode:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
Une autre considération pour les performances est que &String, &Vecet &Boxintroduisez une couche d'indirection inutile car vous devez déréférencer le &Stringpour obtenir un String, puis effectuer une deuxième déréférence pour aboutir à &str.
Au lieu de cela, vous devriez accepter une chaîne slice ( &str), une slice ( &[T]) ou simplement une référence ( &T). A &String, &Vec<T>ou &Box<T>sera automatiquement forcé à a &str, &[T]ou &T, respectivement.
fn awesome_greeting(name: &str) {
println!("Wow, you are awesome, {}!", name);
}
fn total_price(prices: &[i32]) -> i32 {
prices.iter().sum()
}
fn is_even(value: &i32) -> bool {
*value % 2 == 0
}
Vous pouvez désormais appeler ces méthodes avec un ensemble plus large de types. Par exemple, awesome_greetingpeut être appelé avec une chaîne littérale ( "Anna") ou allouée String. total_pricepeut être appelé avec une référence à un tableau ( &[1, 2, 3]) ou un fichier alloué Vec.
Si vous souhaitez ajouter ou supprimer des éléments du Stringou Vec<T>, vous pouvez prendre une référence mutable ( &mut Stringou &mut Vec<T>):
fn add_greeting_target(greeting: &mut String) {
greeting.push_str("world!");
}
fn add_candy_prices(prices: &mut Vec<i32>) {
prices.push(5);
prices.push(25);
}
Spécifiquement pour les tranches, vous pouvez également accepter un &mut [T]ou &mut str. Cela vous permet de muter une valeur spécifique à l'intérieur de la tranche, mais vous ne pouvez pas modifier le nombre d'éléments à l'intérieur de la tranche (ce qui signifie qu'elle est très limitée pour les chaînes):
fn reset_first_price(prices: &mut [i32]) {
prices[0] = 0;
}
fn lowercase_first_ascii_character(s: &mut str) {
if let Some(f) = s.get_mut(0..1) {
f.make_ascii_lowercase();
}
}
&strest plus général (comme dans: impose moins de restrictions) sans capacités réduites"? Aussi: le point 3 n'est souvent pas si important que je pense. Habituellement,Vecs etStrings vivront sur la pile et souvent même quelque part près du cadre de pile actuel. La pile est généralement chaude et le déréférencement sera servi à partir d'un cache CPU.