rust - 在不违反借用规则的情况下,将相同的对象添加到 hashmap 和 vector
问题描述
在与所有权、寿命、移动和借用错误进行了长时间的斗争之后,我在add_turtle_ref
. 期望的行为是add_turtle_ref
将输入添加tref
到self.turtle
s, aVec<TurtleRef>
和self.map
, a HashMap<&str, Vec<TurtleRef>>
。
游乐场。
use std::cell::RefCell;
use std::collections::HashMap;
use std::rc::Rc;
#[derive(Clone)]
pub struct TurtleRef {
t: Rc<RefCell<Turtle>>,
}
impl TurtleRef {
pub fn new(r: Turtle) -> TurtleRef {
TurtleRef {
t: Rc::new(RefCell::new(r)),
}
}
}
pub struct Campus<'a> {
turtles: Vec<TurtleRef>,
map: HashMap<&'a str, Vec<TurtleRef>>,
}
impl Campus<'_> {
pub fn new() -> Campus<'static> {
Campus {
turtles: Vec::new(),
map: HashMap::new(),
}
}
pub fn size(&self) -> usize {
self.turtles.len()
}
pub fn add_turtle(&mut self, turtle: Turtle) {
self.add_turtle_ref(TurtleRef::new(turtle));
}
pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
self.turtles.push(tref.clone());
let n = tref.t.borrow().name();
self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
}
pub fn breed_turtles(&mut self, t1_index: usize, t2_index: usize, child_name: String) {
let n = self.size();
if t1_index > n - 1 || t2_index > n - 1 {
panic!("out of bounds");
}
let tref = Turtle::breed(
&mut self.turtles[t1_index].t.borrow_mut(),
&mut self.turtles[t2_index].t.borrow_mut(),
child_name,
);
self.add_turtle_ref(TurtleRef { t: tref });
}
}
#[derive(Debug)]
pub struct Turtle {
name: String,
children: Vec<Rc<RefCell<Turtle>>>,
}
impl Turtle {
pub fn new(name: String) -> Turtle {
Turtle {
name: name,
children: Vec::new(),
}
}
pub fn name(&self) -> &String {
&self.name
}
pub fn add_child(&mut self, t: Rc<RefCell<Turtle>>) {
self.children.push(t);
}
pub fn breed(t1: &mut Turtle, t2: &mut Turtle, name: String) -> Rc<RefCell<Turtle>> {
let s = Rc::new(RefCell::new(Turtle {
name: name,
children: Vec::new(),
}));
t1.add_child(Rc::clone(&s));
t2.add_child(Rc::clone(&s));
s
}
}
错误:
error[E0597]: `tref.t` does not live long enough
--> src/lib.rs:38:17
|
36 | pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
| --------- has type `&mut Campus<'1>`
37 | self.turtles.push(tref.clone());
38 | let n = tref.t.borrow().name();
| ^^^^^^ borrowed value does not live long enough
39 | self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
| ----------------- argument requires that `tref.t` is borrowed for `'1`
40 | }
| - `tref.t` dropped here while still borrowed
error[E0716]: temporary value dropped while borrowed
--> src/lib.rs:38:17
|
36 | pub fn add_turtle_ref(&mut self, tref: TurtleRef) {
| --------- has type `&mut Campus<'1>`
37 | self.turtles.push(tref.clone());
38 | let n = tref.t.borrow().name();
| ^^^^^^^^^^^^^^^ - temporary value is freed at the end of this statement
| |
| creates a temporary which is freed while still in use
39 | self.map.entry(n).or_insert(Vec::new()).push(tref.clone());
| ----------------- argument requires that borrow lasts for `'1`
我尝试了各种巧妙的技巧,例如获取名称,将其取消引用为普通字符串,然后将其String
转回 a &String
,但这只会导致 Rust 编译器更快地抱怨:你不能取消引用字符串!
解决方案
推荐阅读
- graphql - Apollo GraphQL 服务器中的突变调用有什么问题?
- amazon-web-services - 使用 github 和 AWS lambda 的最佳实践?
- c# - 无法将用户上下文 ID 发送到 Azure Application Insights
- python - RecursionError:我正在寻找一种减少循环次数的方法
- c# - C# 读取 Xml - LinQ
- javascript - 我的 jQuery (touchstart) 不能在 iPhone 上运行
- xml - 如何根据另一个已排序的列表在 XSL 中排序?
- javascript - 使用 libnpm 以编程方式打包和发布 NPM 包
- azure - 从湖中读取数据
- java - JPA & Criteria API 特定选择,使用 select 提取