TL; DR: замість того, щоб можна використовувати &str, &[T]або &Tдля забезпечення більш загального коду.
Однією з головних причин використання a Stringабо a Vecє те, що вони дозволяють збільшити або зменшити ємність. Однак, приймаючи незмінні посилання, ви не можете використовувати жоден із цих цікавих методів на Vecабо String.
Прийом &String, &Vecабо &Boxж вимагає аргумент , щоб бути виділена в купі , перш ніж ви можете викликати функцію. Прийняття дозволу &strдає рядковий літерал (збережений у програмі) та приймає &[T]або &Tдозволяє масив або змінну, виділену стеком. Непотрібний розподіл - це втрата продуктивності. Зазвичай це виявляється відразу, коли ви намагаєтеся викликати ці методи в тесті або mainметоді:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
Ще один розгляд продуктивності полягає в тому &String, що &Vecі &Boxвведіть непотрібний шар непрямості, оскільки вам доведеться знеструмити значення, &Stringщоб отримати а, Stringа потім виконати другий відвід, щоб закінчитися в &str.
Натомість слід прийняти рядковий фрагмент ( &str), фрагмент ( &[T]) або просто посилання ( &T). A &String, &Vec<T>або &Box<T>буде автоматично примусово до a &str, &[T]або &T, відповідно.
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
}
Тепер ви можете викликати ці методи ширшим набором типів. Наприклад, awesome_greetingможна викликати рядковим літералом ( "Anna") або виділеним String. total_priceможна назвати з посиланням на масив ( &[1, 2, 3]) або виділений Vec.
Якщо ви хочете додати або видалити елементи з Stringабо Vec<T>, ви можете скористатися змінною посиланням ( &mut Stringабо &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);
}
Спеціально для скибочок ви також можете прийняти &mut [T]або &mut str. Це дозволяє мутувати певне значення всередині фрагмента, але ви не можете змінити кількість елементів всередині фрагмента (це означає, що це дуже обмежено для рядків):
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();
}
}
&strбільш загальне (як у: накладає менше обмежень) без знижених можливостей"? Також пункт 3 часто не є таким важливим, як я думаю. ЗазвичайVecs іStrings житимуть у стеці, а часто навіть десь біля поточного кадру стека. Стек зазвичай гарячий, і дереференція подаватиметься з кешу CPU.