3

我有一个借用的函数,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必须是 type &String,意思是借来的 string,因为拥有的集合是借来的。那正确吗?

  • 与上述观点类似,我是否正确假设posis 是类型&u16,因为它从 中获取借来的值ids

4

3 回答 3

9

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

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

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

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

此外,它不返回元素的值,只返回一个引用。如果它返回该值,则内部的值HashMap将不再由 the 拥有HashMap,因此将来无法访问。

于 2016-06-09T08:14:47.433 回答
4

TL;DR:Rust 不是 Java。

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

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

案例1:按值取键。

如果键是 a String,这意味着为每次查找分配(和解除分配)内存,而您可以使用只分配一次的本地缓冲区。

情况2:按值返回。

按值返回意味着:

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

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

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

因此,就效率而言,Rust 采取了最合乎逻辑的选择,并在可行时按值传递和返回。

于 2016-06-09T09:48:10.050 回答
3

虽然当键是 a 时似乎没有帮助u16,但想想它如何与更复杂的键一起工作,例如 a String

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

于 2016-06-09T08:55:12.190 回答