TL;DR:可以改为使用&str
,&[T]
或&T
允许更通用的代码。
String
使用 a或 a的主要原因之一Vec
是因为它们允许增加或减少容量。但是,当您接受不可变引用时,您不能在Vec
or上使用任何这些有趣的方法String
。
接受&String
, &Vec
or&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 String
or &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();
}
}