为什么我需要取消引用 HashMap 的键两次?
Why do I need to dereference HashMap's key twice?
我才学 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);
}
你只需要解引用一次
这是您的代码的 example
由于您没有指定 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
on &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
替换要插入的key。
您的 HashMap
的完整类型被推断为 HashMap<&i32, i32>
。这可以通过 using the following trick:
来验证
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
.
我才学 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);
}
你只需要解引用一次
这是您的代码的 example
由于您没有指定 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
on &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
替换要插入的key。
您的 HashMap
的完整类型被推断为 HashMap<&i32, i32>
。这可以通过 using the following trick:
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
.