为什么我需要取消引用 HashMap 的密钥两次?



我只学习了几天 Rust。我认为这两个代码示例是相同的,但编译器不同意。你能解释一下第二部分发生了什么吗?为什么我需要取消引用key两次,但value一次?

第一部分

use std::collections::HashMap;
let mut h = HashMap::new();   
h.insert(1, 1);
h.insert(2, 2);
let mut keys: Vec<i32> = Vec::new();
let mut values: Vec<i32> = Vec::new();
for (k, v) in &h {
keys.push(**k);
values.push(*v);
}

第二部分

fn main() {
let mut v = vec![2, 3, 5, 1, 2, 3, 8, 6, 3, 1, 4, 6, 7];
use std::collections::HashMap;
let mut h = HashMap::new();
for element in &v {
let count = h.entry(element).or_insert(0);
*count += 1;
}
let mut keys: Vec<i32> = Vec::new();
let mut values: Vec<i32> = Vec::new();
for (k, v) in &h {
keys.push(**k);
values.push(*v);
}
println!("{:?}", keys);
}

由于您没有指定HashMap的类型,编译器对其进行了推断。

let v = vec![1i32, 2, 3];
let mut h = HashMap::new();
for i in &v {
h.insert(i, ());
}

这里的h类型是HashMap<&i32, ()>i的类型是&i32。为什么i&i32类型?因为这就是IntoIterator&Vec的实施方式。通常,当您循环访问引用时,您将获得引用。

如果您想要密钥类型不是引用的HashMap,您可以这样说。然后,当您尝试插入引用时,您将收到不同的错误消息。

let v = vec![1i32, 2, 3];
let mut h: HashMap<i32, ()> = HashMap::new();
for i in &v {
h.insert(i, ());
}
error[E0308]: mismatched types
--> src/main.rs:6:18
|
6 |         h.insert(i, ());
|                  ^ expected i32, found &i32
|
= note: expected type `i32`
found type `&i32`

然后你可以用*i替换要插入的键。

HashMap的完整类型推断为HashMap<&i32, i32>。这可以通过使用以下技巧进行验证:

let () = h;

触发类型错误:

error[E0308]: mismatched types
--> src/main.rs:17:9
|
17 |     let () = h;
|         ^^ expected struct `std::collections::HashMap`, found ()
|
= note: expected type `std::collections::HashMap<&{integer}, {integer}>`
found type `()`

(此时编译器还不确定最终类型是否会HashMap<&i32, i32>,因此类型签名中的{integer}s(

当你迭代&h时,(k, v)元组的类型是(&&i32, &i32)(也可以用前面提到的技巧来确认(,这就是为什么你需要对k进行双重取消引用,而对v只需要一个取消引用。

你只需要取消引用一次

下面是代码工作的示例

最新更新