首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >了解锈病`Rc<RefCell<_>>`

了解锈病`Rc<RefCell<_>>`
EN

Stack Overflow用户
提问于 2022-02-02 14:09:12
回答 1查看 499关注 0票数 3

我正在尝试创建一个类型定义类似于

代码语言:javascript
复制
#[derive(Debug, Clone)]
pub(crate) struct TreeBox<T> {
    root: Option<Box<NodeBox<T>>>,
}

#[derive(Debug, Clone)]
struct NodeBox<T> {
    value: T,
    left: Option<Box<NodeBox<T>>>,
    right: Option<Box<NodeBox<T>>>,
}

带插入函数

代码语言:javascript
复制
impl<T: Ord> TreeBox<T> {
    fn new() -> Self {
        Self { root: None }
    }

    pub fn insert(&mut self, value: T) -> bool {
        let mut node = &mut self.root;

        while let Option::Some(current_node) = node {
            match current_node.value.cmp(&value) {
                Ordering::Less => node = &mut current_node.right,
                Ordering::Equal => return false,
                Ordering::Greater => node = &mut current_node.left,
            }
        }

        *node = Option::Some(Box::new(NodeBox {
            value,
            left: Option::None,
            right: Option::None,
        }));

        return true;
    }
}

这是非常完美的,我对这个实现非常满意。但是,我想存储一个从每个节点到它的父节点的引用。经过一些研究,我发现这个文章描述了一个使用RefCellWeak结构的实现。

有了这些知识,我的计划是从上面更新这个例子。我的想法是我可以用Rc<RefCell<..>>代替Rc<RefCell<..>>。我的想法是,这些类型非常相似,因为它们都存储了对某些数据结构的引用,唯一的区别是可以有多个Rc<RefCell<..>>指向该数据结构。

代码语言:javascript
复制
#[derive(Debug, Clone)]
pub(crate) struct Tree<T> {
    root: Option<Rc<RefCell<Node<T>>>>,
}

#[derive(Debug, Clone)]
struct Node<T> {
    value: T,
    left: Option<Rc<RefCell<Node<T>>>>,
    right: Option<Rc<RefCell<Node<T>>>>,
}

impl<T: Ord> Tree<T> {
    fn new() -> Self {
        Self { root: None }
    }

    pub fn insert(&mut self, value: T) -> bool {
        let mut node = &mut self.root;

        while let Option::Some(current_node) = node {
            let cmp = current_node.borrow().value.cmp(&value);
            match cmp {
                Ordering::Less => node = &mut current_node.borrow_mut().right,
                Ordering::Equal => return false,
                Ordering::Greater => node = &mut current_node.borrow_mut().left,
            };
        }

        *node = Option::Some(Rc::new(RefCell::new(Node {
            value,
            left: Option::None,
            right: Option::None,
        })));

        return true;
    }
}

但是,这个更新的示例没有运行,并称

代码语言:javascript
复制
error[E0716]: temporary value dropped while borrowed
  --> src/lib.rs:28:47
   |
28 |                 Ordering::Less => node = &mut current_node.borrow_mut().right,
   |                                               ^^^^^^^^^^^^^^^^^^^^^^^^^     -
   |                                               |                             |
   |                                               |                             temporary value is freed at the end of this statement
   |                                               |                             ... and the borrow might be used here, when that temporary is dropped and runs the destructor for type `RefMut<'_, Node<T>>`
   |                                               creates a temporary which is freed while still in use
   |                                               a temporary with access to the borrow is created here ...
   |
   = note: consider using a `let` binding to create a longer lived value

我的例子是错的,还是我对生锈Rc<RefCell<_>>还不太了解?

一个指向操场的链接,上面的例子如下:https://play.rust-lang.org/?version=stable&mode=debug&edition=2021&gist=9929b2118e2430f03035da4c65a4cf2f

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2022-02-02 15:00:29

所以,你有一些问题。主要的一点是,您尝试接受对Option的引用,该引用包含一个值,该值的生存期很短,因为它与borrow() on RefCell绑定。(在borrow_mut就位时,您也在尝试使用borrow,这会引起恐慌。)值得庆幸的是,Rc使获取对Rc的引用的所有权变得很便宜和容易(这就是关键所在),所以这个问题可以通过存储Option而不是&Option来解决,并且可以自由地克隆包含的Rc。我们使用Option::as_ref&Option<Rc<_>>转换为Option<&Rc<_>>,然后通过在Option<&Rc<_>>上映射Rc::clone将其转换为Option<Rc<_>>

代码语言:javascript
复制
pub fn insert(&mut self, value: T) -> bool {
    let mut node = self.root.as_ref().map(Rc::clone);

    while let Some(current_node) = node {
        let current_node = current_node.borrow();
        let cmp = current_node.value.cmp(&value);
        let new_node = match cmp {
            Ordering::Less => &current_node.left,
            Ordering::Equal => return false,
            Ordering::Greater => &current_node.right,
        };
        node = new_node.as_ref().map(Rc::clone);
    }

    let node = &mut node;
    *node = Some(Rc::new(RefCell::new(Node {
        value,
        left: None,
        right: None,
    })));

    true
}
票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/70957110

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档