为什么借用的 HashMap 的键和值是通过引用访问的,而不是值?
Why are the keys and values of a borrowed HashMap accessed by reference, not value?
我有一个函数需要借用 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
类型,意思是 借用的字符串 ,因为拥有collection是借来的。是吗?
与上述观点类似,我假设 pos
是类型 &u16
是否正确,因为它从 ids
中借用值?
考虑将参数作为引用或值传递的语义:
作为参考:没有所有权转让。被调用的函数只是借用了参数。
作为值:被调用函数拥有参数的所有权,调用者可能不再使用它。
由于函数 HashMap::get
不需要键的所有权来查找元素,因此选择了限制较少的传递方法:通过引用。
另外,它没有return元素的值,只是一个参考。如果它 returned 值,HashMap
中的值将不再由 HashMap
拥有,因此将来无法访问。
虽然当密钥是 u16
时它似乎没有帮助,但请考虑如何使用更复杂的密钥,例如 String
。
在那种情况下,按值获取键通常意味着必须为每次查找分配和初始化一个新的 String
,这会很昂贵。
TL;DR:Rust 不是 Java。
Rust 可能具有高级构造和数据结构,但它本质上是一种低级语言,正如其指导原则之一所说明的那样:你不需要为什么付费你不使用.
因此,该语言及其库将尽可能地尝试消除任何多余的成本,例如不必要地分配内存。
案例一:按值取键
如果键是 String
,这意味着为每次查找分配(和释放)内存,而您可以使用只分配一次的本地缓冲区。
案例二:按值返回
按值返回意味着:
- 您从容器中删除条目以将其提供给用户
- 您复制容器中的条目以将其提供给用户
后者显然效率低下(复制意味着分配),前者意味着如果用户想要取回值,则必须再次插入,这意味着查找等......并且效率也很低。
简而言之,在这种情况下按值返回是低效的。
因此,就效率而言,Rust 采取了最合乎逻辑的选择,并在可行的情况下按价值传递 returns。
我有一个函数需要借用 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
类型,意思是 借用的字符串 ,因为拥有collection是借来的。是吗?与上述观点类似,我假设
pos
是类型&u16
是否正确,因为它从ids
中借用值?
考虑将参数作为引用或值传递的语义:
作为参考:没有所有权转让。被调用的函数只是借用了参数。
作为值:被调用函数拥有参数的所有权,调用者可能不再使用它。
由于函数 HashMap::get
不需要键的所有权来查找元素,因此选择了限制较少的传递方法:通过引用。
另外,它没有return元素的值,只是一个参考。如果它 returned 值,HashMap
中的值将不再由 HashMap
拥有,因此将来无法访问。
虽然当密钥是 u16
时它似乎没有帮助,但请考虑如何使用更复杂的密钥,例如 String
。
在那种情况下,按值获取键通常意味着必须为每次查找分配和初始化一个新的 String
,这会很昂贵。
TL;DR:Rust 不是 Java。
Rust 可能具有高级构造和数据结构,但它本质上是一种低级语言,正如其指导原则之一所说明的那样:你不需要为什么付费你不使用.
因此,该语言及其库将尽可能地尝试消除任何多余的成本,例如不必要地分配内存。
案例一:按值取键
如果键是 String
,这意味着为每次查找分配(和释放)内存,而您可以使用只分配一次的本地缓冲区。
案例二:按值返回
按值返回意味着:
- 您从容器中删除条目以将其提供给用户
- 您复制容器中的条目以将其提供给用户
后者显然效率低下(复制意味着分配),前者意味着如果用户想要取回值,则必须再次插入,这意味着查找等......并且效率也很低。
简而言之,在这种情况下按值返回是低效的。
因此,就效率而言,Rust 采取了最合乎逻辑的选择,并在可行的情况下按价值传递 returns。