TL;DR:可以改为使用&str
, &[T]
or &T
以允许更通用的代码。
-
使用的主要原因之一String
or a Vec
是因为它们允许增加或减少容量。但是,当您接受不可变引用时,您无法在Vec
or String
.
-
接受一个&String
, &Vec
or &Box
also requires调用函数之前要在堆上分配的参数。接受一个&str
允许字符串文字(保存在程序数据中)并接受&[T]
or &T
允许堆栈分配的数组或变量。不必要的分配是性能损失。当您尝试在测试或测试中调用这些方法时,这通常会立即暴露出来。main
method:
awesome_greeting(&String::from("Anna"));
total_price(&vec![42, 13, 1337])
is_even(&Box::new(42))
-
另一个性能考虑因素是&String
, &Vec
and &Box
引入不必要的间接层,因为您必须取消引用&String
得到一个String
然后执行第二次取消引用以结束&str
.
相反,您应该接受字符串切片 (&str
), a slice (&[T]
),或者只是一个参考(&T
). A &String
, &Vec<T>
or &Box<T>
将被自动强制(通过解除引用强制 https://doc.rust-lang.org/stable/reference/type-coercions.html#coercion-types) to 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"
) or分配的String
. total_price
可以通过引用数组来调用(&[1, 2, 3]
) or分配的Vec
.
如果您想添加或删除项目String
or 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);
}
特别是对于切片,您还可以接受&mut [T]
or &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();
}
}