为什么通过引用访问借用的HashMap的键和值,而不是值?

时间:2016-06-09 08:00:06

标签: collections rust ownership borrowing

我有一个借用HashMap的函数,我需要按键访问值。为什么键和值是通过引用而不是值?

我的简化代码:

fn print_found_so(ids: &Vec<i32>, file_ids: &HashMap<u16, String>) {
    for pos in ids {
        let whatever: u16 = *pos as u16;
        let last_string: &String = file_ids.get(&whatever).unwrap();

        println!("found: {:?}", last_string);
    }
}
  • 为什么我必须指定密钥作为参考,即file_ids.get(&whatever).unwrap()而不是file_ids.get(whatever).unwrap()

  • 据我了解,last_string必须是&String类型,这意味着借用字符串,因为借用了拥有的集合。是吗?

  • 与上述类似,我认为pos的类型为&u16是正确的,因为它需要ids中的借来的值吗?

3 个答案:

答案 0 :(得分:8)

考虑将参数作为引用或值传递的语义:

  • 作为参考:没有所有权转让。被调用函数只是借用参数。

  • 作为值:被调用的函数取得参数的所有权,并且可能不再被调用者使用。

由于函数HashMap::get不需要密钥的所有权来查找元素,因此选择了限制较少的传递方法:通过引用。

此外,它不返回元素的值,只返回引用。如果它返回了值,则HashMap中的值将不再由HashMap拥有,因此将来无法访问。

答案 1 :(得分:3)

虽然当密钥为u16时似乎无用,但请考虑如何使用更复杂的密钥(例如String

在这种情况下,按值获取密钥通常意味着必须为每次查找分配和初始化新的String,这将是昂贵的。

答案 2 :(得分:3)

TL; DR :Rust不是Java。

Rust可能具有高级构造和数据结构,但它本质上是一种低级语言,如其指导原则之一所示:你不支付你不支付的费用使用

因此,语言及其库将尽可能地尝试消除任何多余的成本,例如不必要地分配内存。

案例1:按值获取密钥。

如果密钥是String,这意味着当您可以使用仅一次性分配的本地缓冲区时,为每次查找分配(和解除分配)内存。

案例2:按价值返回。

按值返回意味着:

  • 您从容器中删除条目以将其提供给用户
  • 您复制容器中的条目以将其提供给用户

后者显然效率低(复制意味着分配),前者意味着如果用户希望在另一次插入中返回值必须再次发生,这意味着查找等......并且效率也很低。

简而言之,在这种情况下,按值返回效率很低。

因此,就效率而言,Rust是最合乎逻辑的选择,并且只要实际可行,就会传递并返回值。