Ответ 1
TL; DR: вместо этого можно использовать &str
, &[T]
или &T
для более общего кода.
-
Одна из основных причин использования
String
или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>
будут автоматически приводиться к &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();
}
}