【问题标题】:Why do I need to dereference HashMap's key twice?为什么我需要两次取消引用 HashMap 的键?
【发布时间】:2018-01-20 00:08:21
【问题描述】:

我才学习 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 rust dereference


    【解决方案1】:

    你只需要取消引用一次

    这是您的代码工作的example

    【讨论】:

    • 你能看看我的补充吗?
    【解决方案2】:

    由于您没有指定 HashMap 的类型,因此编译器推断了它。

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

    这里h的类型是HashMap&lt;&amp;i32, ()&gt;i的类型是&amp;i32。为什么i 的类型是&amp;i32?因为这就是&amp;Vec 上的IntoIterator 的实现方式。通常,当您迭代引用时,您会得到引用。

    如果您想要一个键类型不是引用的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

    【讨论】:

      【解决方案3】:

      您的HashMap 的完整类型被推断为HashMap&lt;&amp;i32, i32&gt;。这可以通过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&lt;&amp;i32, i32&gt;,因此类型签名中的{integer}s)

      当您迭代 &amp;h 时,(k, v) 元组的类型为 (&amp;&amp;i32, &amp;i32)(也可以通过上述技巧来确认),这就是为什么您需要对 k 进行双重取消引用,而对于 k 只有一个v.

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-06-22
        • 2022-07-12
        • 2019-08-07
        • 1970-01-01
        • 2015-04-03
        • 1970-01-01
        • 2013-04-01
        • 1970-01-01
        相关资源
        最近更新 更多