TL;DR : On peut à la place utiliser &str
, &[T]
o &T
pour permettre un code plus générique.
-
L'une des principales raisons d'utiliser un String
ou un Vec
c'est parce 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 fichier Vec
o String
.
-
Accepter un &String
, &Vec
o &Box
également nécessite l'argument doit être alloué sur le tas avant que vous puissiez appeler la fonction. Accepter un &str
permet un littéral de chaîne de caractères (sauvegardé dans les données du programme) et accepte un &[T]
o &T
permet un tableau ou une variable allouée à la pile. Une allocation inutile entraîne une perte de performance. Ce problème est généralement mis en évidence dès que vous essayez d'appeler ces méthodes dans un test ou dans un fichier main
méthode :
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
-
Une autre considération de performance est que &String
, &Vec
y &Box
introduisent une couche inutile d'indirection, car vous devez déréférencer l'adresse de l'utilisateur. &String
pour obtenir un String
puis effectuer une deuxième déréférence pour aboutir à &str
.
Au lieu de cela, vous devez accepter un tranche de chaîne ( &str
), a tranche ( &[T]
), ou juste une référence ( &T
). A &String
, &Vec<T>
o &Box<T>
sera automatiquement contraint (via deref coercition ) à un &str
, &[T]
o &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_greeting
peut être appelé avec une chaîne littérale ( "Anna"
) ou une allocation String
. total_price
peut être appelé avec une référence à un tableau ( &[1, 2, 3]
) ou une allocation Vec
.
Si vous souhaitez ajouter ou supprimer des éléments de la liste des String
o Vec<T>
vous pouvez prendre un référence mutable ( &mut String
o &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 une &mut [T]
o &mut str
. Cela vous permet de modifier 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 que c'est très limité pour les chaînes de caractères) :
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();
}
}