在我的代码中,我有一个相互递归的树结构,如下所示:
enum Child<'r> {
A(&'r Node<'r>),
B,
C
}
struct Node<'r> {
children : [&'r Child<'r>,..25]
}
impl <'r>Node<'r> {
fn new() -> Node {
Node {
children : [&B,..25]
}
}
}
但它不按原样编译。修改它的最佳方法是什么?
答案 0 :(得分:4)
这是一个可以从树外修改节点的版本,我认为这是要求的。
use std::rc::Rc;
use std::cell::RefCell;
struct Node {
a : Option<Rc<RefCell<Node>>>,
b : Option<Rc<RefCell<Node>>>,
value: int
}
impl Node {
fn new(value: int) -> Rc<RefCell<Node>> {
let node = Node {
a: None,
b: None,
value: value
};
Rc::new(RefCell::new(node))
}
}
fn main() {
let first = Node::new(0);
let second = Node::new(0);
let third = Node::new(0);
first.borrow_mut().a = Some(second.clone());
second.borrow_mut().a = Some(third.clone());
second.borrow_mut().value = 1;
third.borrow_mut().value = 2;
println!("Value of second: {}", first.borrow().a.get_ref().borrow().value);
println!("Value of third: {}", first.borrow().a.get_ref().borrow().a.get_ref().borrow().value);
}
Rc
是一个引用计数指针,允许单个对象拥有多个所有者。但它不允许突变,因此需要RefCell
,允许运行时检查可变借用。这就是代码使用Rc<RefCell<Node>>
的原因。 Option类型用于表示具有Option<Rc<RefCell<Node>>>
的潜在子女。
由于Rc类型自动解除引用,因此可以直接在其上调用RefCell方法。这些是borrow()
和borrow_mut()
,它们返回对底层节点的引用和可变引用。还存在try_borrow()
和try_borrow_mut()
变体,这些变体不会失败。
get_ref()
是Option类型的一种方法,它返回对底层Rc<RefCell<Node>>
的引用。在一个真实的peogram中,我们可能想要检查Option是否包含任何东西。
为什么原始代码不起作用?引用&T
意味着非所有权,因此其他东西必须拥有节点。虽然可以构建&Node
类型的树,但是在树之外修改节点是不可能的,因为一旦借用,对象就不能被借用对象以外的任何东西修改。