Rust借用指针和生命周期

时间:2014-04-17 14:06:13

标签: rust

在我的代码中,我有一个相互递归的树结构,如下所示:

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]
        } 
    }
}

但它不按原样编译。修改它的最佳方法是什么?

1 个答案:

答案 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类型的树,但是在树之外修改节点是不可能的,因为一旦借用,对象就不能被借用对象以外的任何东西修改。