如何创建包含对另一个hashmap元素的引用的hashmap?

我正在尝试创建一个包含两个哈希映射的结构 - 一个具有一些值,另一个引用另一个hashmap的元素 . 这是我的代码 .

use std::collections::HashMap;

struct Foo;
struct Bar<'s>(&'s Foo);

struct MyStruct<'a> {
    first : HashMap<&'a str, Foo>,
    second : HashMap<&'a str, Bar<'a>>,
}

impl<'a> MyStruct<'a> {
    fn new() -> MyStruct<'a> {
        let mut result = MyStruct {
            first : HashMap::new(),
            second : HashMap::new(),
        };
        match result.first.get("") {
            Some(t) => { result.second.insert("", Bar(t)); },
            None => {},
        }
        result
    }
}

fn main() {
}

并且此代码无法编译并出现以下错误:

错误:result.first不够长寿

我认为这个问题与生命有关,但我无法清楚地解释什么是错的 .

任何人都可以解释发生了什么以及如何解决这个错误?

附: struct FooBar 来自库,所以我无法修改这些结构 .

回答(1)

3 years ago

问题确实与所有权/借款/生命周期有关 .

通常,在Rust中,不可能(安全地)在兄弟属性中引用引用;因此 .second 指向 .first 是不可能的 .

但是,即使你将它分成两个结构,你仍会遇到问题,因为引用 HashMap 借用它(这意味着只要引用存在,修改 HashMap 是被禁止的),这可能不是你的意思希望 .

在这种情况下,通过简单地共享存储器可以避免最后的障碍;例如,两个 HashMap 分别使用 Rc<X> 值而不是 X&'a X ...

...但是,鉴于 FooBar<'a> 类型,这对您的特定问题没有帮助 .

您可以将结构更改为:

struct MyStruct<'a, 'b> {
    first: HashMap<&'a str, &'b Foo>,
    second: HashMap<&'a str, Bar<'b>>,
}

然后在其他地方维护实际的 Foo 个实例 . 如果你需要在保持 HashMap 的同时分配那些 Foo 的可能性是使用竞技场分配,例如Arena<Foo> .