TL;DR:可以改为使用&str,&[T]或&T允许更通用的代码。
String使用 a或 a的主要原因之一Vec是因为它们允许增加或减少容量。但是,当您接受不可变引用时,您不能在Vecor上使用任何这些有趣的方法String。
接受&String, &Vecor&Box还需要在调用函数之前在堆上分配参数。接受 a&str允许字符串文字(保存在程序数据中)并接受 a &[T]or&T允许堆栈分配的数组或变量。不必要的分配是性能损失。当您尝试在测试或方法中调用这些方法时,这通常会立即暴露main:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
另一个性能考虑因素是&String,&Vec并&Box引入了不必要的间接层,因为您必须取消引用&String以获取 aString然后执行第二次取消引用以结束 at &str。
相反,您应该接受字符串切片( &str)、切片( &[T]) 或只是一个引用 ( &T)。A &String, &Vec<T>or&Box<T>将被自动强制(通过deref coercion)分别为 a &str, &[T]or &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。
如果您想在 or 中添加或删除项目String,Vec<T>您可以使用可变引用( &mut Stringor &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);
}
特别是对于切片,您还可以接受 a&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();
}
}