【问题标题】:Lifetimes in HashMap where key refers to valueHashMap 中的生命周期,其中键是指值
【发布时间】:2020-04-03 21:41:06
【问题描述】:

我对 Rust 比较陌生。我想编写一个函数,该函数将从给定一个从值生成键的闭包的集合中创建一个 HashMap,例如

[derive(Debug)]
struct Foo {
    id: u32,
    name: String,
}
let foos = vec![
    Foo { id: 1, name: "Bill".to_string() },
    Foo { id: 2, name: "Mary".to_string() },
];
println!("{:?}", foos);
println!("{:?}", map_by(foos.iter(), |f|  f.id));  // borrow  the Foos
println!("{:?}", map_by(foos.iter(), |f| &f.name));          // borrow
println!("{:?}", map_by(foos.iter(), |f|  f.name.as_str())); // borrow
println!("{:?}", map_by(foos,        |f|  f.id));  // consume the Foos

我写了这个,它适用于上述用途:

fn map_by<I,K,V>(iterable: I, f: impl Fn(&V) -> K) -> HashMap<K,V>
where I: IntoIterator<Item = V>,
      K: Eq + Hash
{
    iterable.into_iter().map(|v| (f(&v), v)).collect()
}

[Foo { id: 1, name: "Bill" }, Foo { id: 2, name: "Mary" }]
{1: Foo { id: 1, name: "Bill" }, 2: Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{"Bill": Foo { id: 1, name: "Bill" }, "Mary": Foo { id: 2, name: "Mary" }}
{2: Foo { id: 2, name: "Mary" }, 1: Foo { id: 1, name: "Bill" }}

太棒了!但是当我让 HashMap OWN 键引用它们的值时它不起作用:

println!("{:?}", map_by(foos,        |f| f.name.as_str()));

error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements

不幸的是,错误消息使我的大脑融化了。我尝试指定键和值具有相同的生命周期,但它没有帮助。 Here it is in a playground。编译器试图告诉我什么,我做错了什么?当然,如果我们借用这些值时这可以工作,那么当我们拥有它们时它也可以工作。

【问题讨论】:

    标签: rust


    【解决方案1】:

    当然,如果我们借用这些值时它可以工作,那么当我们拥有它们时它也可以工作。

    没有。当HashMap 需要调整自身大小以适应新条目时,它会在内存中移动条目。如果key借了value,并且entry被移动了,那么value的地址会发生变化,key中的引用将不再有效。

    有关详细信息,请参阅Why can't I store a value and a reference to that value in the same struct?

    【讨论】:

    • 啊,这有助于解除迷雾。谢谢,弗朗西斯。
    猜你喜欢
    • 2013-03-19
    • 2022-12-04
    • 2017-05-16
    • 1970-01-01
    • 2019-12-18
    • 2021-10-27
    • 2013-01-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多