rust 无法作为可变对象借用,正在从借用值获取可变引用[重复]

2fjabf4q  于 2022-12-29  发布在  其他
关注(0)|答案(1)|浏览(114)
    • 此问题在此处已有答案**:

How to handle "temporary value dropped" error when adapting Box-based tree structure to Rc+RefCell?(2个答案)
昨天关门了。
我在关注另一个帖子:Understanding Rust Rc<RefCell<_>>其中op尝试使用Box实现树,并成功实现了该树,但随后尝试使用Rc和RefCell实现该树,但发现了问题。接受的答案可以编译,但无法运行,因为它不向根添加节点。我尝试稍微更新接受的答案,以使其运行,但无法运行。基本上,我尝试在循环中获取可变引用,但无法'因为我借用了一个不可变的引用,但是如果我得到的borrow_mut()是一个私有字段,那么我假设如果它是一个可变的引用,我不能访问它所包含的值的任何属性?
我该怎么做才能让这段代码正常工作?

use std::borrow::BorrowMut;
use std::cell::RefCell;
use std::cmp::Ordering;
use std::rc::Rc;
use std::fmt;

#[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>>>,
}

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

#[derive(Debug, Clone)]
pub(crate) struct Tree<T> {
    root: Option<Rc<RefCell<Node<T>>>>,
}

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

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

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

        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 => &mut current_node.left,
                Ordering::Equal => return false,
                Ordering::Greater => &mut current_node.right,
            };
            node = new_node;
        }

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

        println!("node: {:?}", node);
        true
    }

}

fn main() {

    let mut tree_box = TreeBox::new();
    tree_box.insert(1);
    tree_box.insert(2);
    tree_box.insert(3);

    let mut tree = Tree::new();
    tree.insert(1);
    tree.insert(2);
    tree.insert(3);

    println!("TreeBox: {:?}", tree_box);
    println!("Tree: {:?}", tree);
}
sauutmhj

sauutmhj1#

接受的答案会进行编译,但不起作用,因为它不会向根添加节点。
你是正确的,并修复原来的解决方案,这里的版本,添加根节点正确:

pub fn insert(&mut self, value: T) -> bool {
        //if no root, just create one
        let mut node = if let Some(root) = &self.root {
            Rc::clone(root)
        } else {
            self.root = Some(Rc::new(RefCell::new(Node {
                value,
                left: None,
                right: None,
            })));
            return true;
        };

        loop {
            let current_node = Rc::clone(&node);
            let mut current_node = RefCell::borrow_mut(&current_node);
            let cmp = current_node.value.cmp(&value);
            let next_node = match cmp {
                Ordering::Less => &mut current_node.left,
                Ordering::Equal => return false,
                Ordering::Greater => &mut current_node.right,
            };
            if let Some(next_node) = next_node {
                node = Rc::clone(next_node);
            } else {
                *next_node = Some(Rc::new(RefCell::new(Node {
                    value,
                    left: None,
                    right: None,
                })));

                println!("node: {:?}", node);
                return true;
            }
        }
    }

基本上,我试图在循环中获得可变引用,但我做不到,因为我借用了一个不可变引用。
问题是稍有不同的,你不能遍历这个Rc<RefCell>树,至少不能像这样交互,因为当你使用它的时候,你的实现需要保留“borrow”,并且在每个循环之后释放“borrow”。
但是如果我得到的borrow_mut()值是私有字段,那么如果它是一个可变引用,我就不能访问它所包含的值的任何属性?
不完全是这样,这里发生的是你调用的函数RefCell::borrow_mut不是返回一个RefMut<Node>,你实际上调用的是返回&mut RefMut<...><Rc as BorrowMut>::borrow_mut,通过访问value你试图从RefCell访问私有字段value,而不是Node
注意,在我的实现中,我显式地调用了RefCell::borrow_mut,这解决了这个问题。

相关问题