rust 存储其他人拥有的可变引用

ee7vknir  于 2022-11-12  发布在  其他
关注(0)|答案(2)|浏览(135)

我想在HashMap中存储结构体,但也要引用另一个结构体向量字段中的相同结构体。
假设我有一个由两种类型的结构体Item和Relation组成的树。
我在HashMap中按id存储所有关系,但我还想用对HashMap所拥有的相同关系结构的可变引用来填充每个item.out_relations向量。
这是我的物品:

pub struct Item<'a> {
  pub id: oid::ObjectId,
  pub out_relations: Vec<&'a mut Relation>, // <-- want to fill this
}

当我迭代从DB中得到的关系时,我试图这样做:

let from_id = relation.from_id; //to find related item
item_map // my items loaded here already
.entry(from_id)
.and_modify(|item| { 
  (*item)
    .out_relations.push(
      relation_map.try_insert(relation.id, relation).unwrap() // mut ref to relation expected here
    )
  }
);

现在,编译器警告try_insert是不稳定的特性,并将我指向这个bug。但是,让我们想象一下,我有一个可变的引用,指向已经由HashMap拥有的关系--它会工作吗?
或者这将再次是一些引用寿命不够长的错误?我有什么选择呢?或者我更好地将只存储关系id在项目out_relations向量而不是引用?当需要时,我将从散列表中获取我的关系?

ftf50wuq

ftf50wuq1#

这就是所谓的共享可变性,它是被借位检查器禁止的。幸运的是Rust提供了安全的工具来实现这一点。在你的例子中,你需要使用Rc,所以你的代码应该是:

pub struct Item {
  pub id: oid::ObjectId,
  pub out_relations: Vec<Rc<RefCell<Relation>>>,
}

当我迭代从DB中得到的关系时,我试图这样做:

let relation = Rc::new(RefCell::new(relation));

let from_id = relation.borrow().from_id; // assuming id is a Copy type
item_map // my items loaded here already
.entry(from_id)
.and_modify(|item| { 
  (*item)
    .out_relations.push(
      relation_map.try_insert(relation.id, relation.clone()).unwrap() // mut ref to relation expected here
    )
  }
);

如果以后想改变关系,可以使用.borrow_mut()

relation.borrow_mut().from_id = new_id;
1u4esq0p

1u4esq0p2#

我同意乌萨马·加穆迪的诊断,但我想提供替代解决方案。
引用计数的问题在于它会降低性能。
在你的向量中,你能不能把键存储到散列Map中?然后,当你需要从向量中获取值时,从向量中获取键,从散列Map中获取值?
另一个策略是保留一个向量值,然后将索引存储到哈希Map中的向量和其他向量中。这位Rust Keynote演讲者很好地描述了这个策略:https://youtu.be/aKLntZcp27M?t=1787

相关问题