首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >为什么从HashMap中获取值时需要两个“&”?

为什么从HashMap中获取值时需要两个“&”?
EN

Stack Overflow用户
提问于 2019-03-04 20:10:12
回答 1查看 861关注 0票数 4

我在rust的推荐信上遇到了点麻烦。我有以下不能编译的代码:

代码语言:javascript
复制
use std::collections::HashMap;

fn main() {
    let mut map = HashMap::new();

    map.insert(&0, &0);
    map.insert(&1, &1);

    assert_eq!(map.get(&0), Some(&0));
}

我得到的编译错误是:

代码语言:javascript
复制
error[E0308]: mismatched types
 --> rust_doubt.rs:9:5
  |
9 |     assert_eq!(map.get(&0), Some(&0));
  |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected &{integer}, found integral variable
  |
  = note: expected type `std::option::Option<&&{integer}>`
             found type `std::option::Option<&{integer}>`
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

error: aborting due to previous error

果然,如果我更改了行:

assert_eq!(map.get(&0), Some(&0)); to assert_eq!(map.get(&0), Some(&&0)); (双与号)代码编译

问题:

  1. map.insert(&0, &0)将指向两个整数文字的指针插入到映射中。我甚至不确定这是如何实现的,因为我没有在任何地方使用变量。我怎么能引用一个文字呢?我原以为编译器会让我这样做:

代码语言:javascript
复制
let a = 0;
let b = 0
map.insert(&a, &b);

换句话说,&0到底是什么意思呢?它是否为文字分配内存并返回对它的引用?如果是这样,那么我假设不会有两个&0指向相同的内存,这是正确的吗?

  1. 为什么我必须使用Some(&&0)而不只是Some(&0)&&0到底是什么意思?我知道**ptr意味着两次取消对变量的引用,以获得底层的值。但我不能完全想象相反的情况-你怎么能两次“引用”一个整型文字呢?
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2019-03-04 20:39:12

如果你看看insertget的签名,你就会意识到他们处理事情的方式是不同的。

HashMap<K, V>开始

  • fn insert(&mut self, k: K, v: V) -> Option<V>.
  • fn get(&self, k: &K) -> Option<&V> (simplified).

如您所见,insert获取所有权,处理,而get获取并返回引用

因此,如果你insert &1,你get Some(&&1) back:再多一层引用。

那么,问题是为什么.get(&0)没有错误:它不是缺少一个引用级别吗?

好吧,我欺骗并简化了get的签名,the exact signature是:

代码语言:javascript
复制
pub fn get<Q: ?Sized>(&self, k: &Q) -> Option<&V> where
    K: Borrow<Q>,
    Q: Hash + Eq, 

事实证明,&T实现了Borrow<T>,因此您可以使用&K&&K调用get。

如果您设法让编译器为您提供HashMap的类型,就会更容易一些:

代码语言:javascript
复制
assert_eq!(map, ());

结果如下:

代码语言:javascript
复制
error[E0308]: mismatched types
 --> src/main.rs:9:5
  |
9 |     assert_eq!(map, ());
  |     ^^^^^^^^^^^^^^^^^^^^ expected struct `std::collections::HashMap`, found ()
  |
  = note: expected type `std::collections::HashMap<&{integer}, &{integer}>`
             found type `()`
  = note: this error originates in a macro outside of the current crate (in Nightly builds, run with -Z external-macro-backtrace for more info)

它显示了编译器为KV计算出的类型,实际上它将是&{integer},因为您将&0传递给insert,它通过值获取键和值。

至于生命周期的问题:

  1. 并非所有检查都是一次性完成的。特别是,借用/生存期检查通常在类型checking.
  2. Literals具有'static生存期之后执行,就像"Hello"具有&'static str类型一样。

编译器会自动在程序中的某处为文字保留内存,并在必要时“借用”它们。这意味着创建一个对文字整数的引用是非常好的:&0i32具有&'static i32类型。

票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/54982977

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档