0

我写了一个代码来解决树问题,Rc RefCell用来包装树节点结构(实际上这部分是由 leetcode 提供的)。

我试图保存这棵树中每个节点的引用计数,但在模式匹配中,我不允许 match q[0].borrow().left.clone(),因为它借用 q[0].borrow() 作为不可变的内联。

我最终得到了一个解决方法,但我无法解释它,并希望能看到针对这种情况的更好解决方案。

#[derive(Debug, PartialEq, Eq)]
pub struct TreeNode {
    pub val: i32,
    pub left: Option<Rc<RefCell<TreeNode>>>,
    pub right: Option<Rc<RefCell<TreeNode>>>,
}

impl TreeNode {
    #[inline]
    pub fn new(val: i32) -> Self {
        TreeNode {
            val,
            left: None,
            right: None,
        }
    }
}

use std::cell::RefCell;
use std::rc::Rc;
struct Solution;

impl Solution {
    pub fn foo(root: Option<Rc<RefCell<TreeNode>>>) {
        let mut q: Vec<Rc<RefCell<TreeNode>>> = vec![];
        if let Some(root_node) = root {
            q.push(root_node);

            // this line I borrow q[0] as immutable, but use it mutably in the next line 
            if let Some(left_node) = q[0].borrow().left.clone() {
                q.push(left_node);
            }
        }
    }
}

错误日志:

error[E0502]: cannot borrow `q` as mutable because it is also borrowed as immutable
  --> main.rs:30:17
   |
29 |             if let Some(left_node) = q[0].borrow().left.clone() {
   |                                      -------------
   |                                      |
   |                                      immutable borrow occurs here
   |                                      a temporary with access to the immutable borrow is created here ...
30 |                 q.push(left_node);
   |                 ^^^^^^^^^^^^^^^^^ mutable borrow occurs here
31 |             }
   |             - ... and the immutable borrow might be used here, when that temporary is dropped and runs the destructor for type `Ref<'_, TreeNode>`

有什么优雅的方法可以实现与上述相同的语义吗?

我的解决方法是:

    pub fn foo(root: Option<Rc<RefCell<TreeNode>>>) {
        let mut q: Vec<Rc<RefCell<TreeNode>>> = vec![];
        if let Some(root_node) = root {
            q.push(root_node);

            let q0_left = q[0].borrow().left.clone();
            if let Some(left_node) = q0_left {
                q.push(left_node);
            }
        }
    }

我也不明白为什么这会避免borrow问题。

4

0 回答 0