一般建议在Rust中接受&str
而不是String
。
假设我有几个函数和一个String
实例:
use std::collections::HashMap;
fn do_something_str(string: &str) {
let mut map = HashMap::new();
map.insert(string.to_owned() /* copying (expensive)? */, "value");
}
fn do_something_string(string: String) {
let mut map = HashMap::new();
map.insert(string /* moving (cheap)? */, "value");
}
fn main() {
let string = String::from("123");
do_something_str(&string);
do_something_string(string);
}
游乐场
复制是否发生在do_something_str()
意味着它将更慢/更高的临时内存消耗?
p。我知道我不需要显式地调用.to_owned()
,下面也可以工作:
fn do_something_str(string: &str) {
let mut map = HashMap::new();
map.insert(string /* copying (expensive)? */, "value");
}
但是由于hashmap拥有键,我相信它会隐式克隆它。如果我说错了,请纠正我。
一般建议在Rust中接受
&str
而不是String
。
不完全是。一般的智慧是接受&str
而不是&String
。也就是说,当您已经打算对引用进行操作时,更通用的类型被认为是更好的。
如果您需要一个拥有的String
,实际上传递一个引用只是为了立即克隆它是浪费的。首先接受String
将选择权留给了调用者:如果他们需要为自己保留字符串的副本,他们可以使用clone()
。否则,调用者只将String
移动到HashMap中,不涉及克隆。
但是由于hashmap拥有键,我相信它会隐式克隆它。如果我说错了,请纠正我。
HashMap
在插入时不克隆。这将需要Clone
性状绑定在HashMap
上。
HashMap<&str, T>
仍然会"own"密钥,但在这种情况下,密钥是&str
,而不是它自己的对等物(String
)。当然,这将防止HashMap
比键引用的字符串更长寿。以下示例未通过借用检查:
use std::collections::HashMap;
fn main() {
let mut map: HashMap<&str, ()> = HashMap::new();
{
let key = String::from("foo");
map.insert(&key, ()); // error[E0597]: `key` does not live long enough
}
println!("{:?}", map.get("foo"));
}
在&str
上调用.to_owned()
确实会创建一个字符串的私有副本,并与相应的性能/内存相关联。
正如您正确指出的,您还可以有一个HashMap<&str, V>
,即HashMap
,其密钥类型为&str
。这并不需要克隆字符串。然而,这意味着HashMap
的生存期受到&str
的生存期的限制。