我想把我的头围绕着Rc
和RefCell
在Rust。我想要实现的是有多个可变的引用到相同的对象。
我想出了这个虚拟代码:
use std::rc::Rc;
use std::cell::RefCell;
struct Person {
name: String,
mother: Option<Rc<RefCell<Person>>>,
father: Option<Rc<RefCell<Person>>>,
partner: Option<Rc<RefCell<Person>>>
}
pub fn main () {
let mut susan = Person {
name: "Susan".to_string(),
mother: None,
father: None,
partner: None
};
let mut boxed_susan = Rc::new(RefCell::new(susan));
let mut john = Person {
name: "John".to_string(),
mother: None,
father: None,
partner: Some(boxed_susan.clone())
};
let mut boxed_john = Rc::new(RefCell::new(john));
let mut fred = Person {
name: "Fred".to_string(),
mother: Some(boxed_susan.clone()),
father: Some(boxed_john.clone()),
partner: None
};
fred.mother.unwrap().borrow_mut().name = "Susana".to_string();
println!("{}", boxed_susan.borrow().name);
// boxed_john.borrow().partner.unwrap().borrow_mut().name = "Susanna".to_string();
// println!("{}", boxed_susan.borrow().name);
}
最有趣的部分是:
fred.mother.unwrap().borrow_mut().name = "Susana".to_string();
println!("{}", boxed_susan.borrow().name)
我更改了fred母亲的名字,然后打印出Susan的名字,这应该是完全相同的引用。令人惊讶的是,它打印出了"Susana",所以我假设我的共享可变引用的小实验是成功的。
然而,现在我想再次改变它,这次访问它作为John的伙伴,这也应该是完全相同的实例。
不幸的是,当我在下面两行注释时:
// boxed_john.borrow().partner.unwrap().borrow_mut().name = "Susanna".to_string();
// println!("{}", boxed_susan.borrow().name);
我遇到了我的老朋友cannot move out of dereference of
&-pointer
。我哪里做错了?
这将修复它:
boxed_john.borrow().partner.as_ref().unwrap().borrow_mut().name = "Susanna".to_string();
问题是Option<Rc<RefCell>>
上的unwrap()
,它消耗了选项(即移出它),但你只有一个借来的指针。as_ref
将Option(T)
转换为Option(&T)
, unwrap
将其转换为&T
,避免任何移动。
还要注意:你的变量具有比它们真正需要的更多的可变性。但我相信你们已经看到了编译器的警告