在使用Rc实现二叉树时,无法将不可变借用内容借用为可变内容

Ale*_*lex 0 rust

我想实现二叉树.我的主要语言是C++,所以代码可能不是惯用的Rust,而是编译以下代码:

use std::rc::Rc;

struct Node {
    left: Option<Rc<Node>>,
    right: Option<Rc<Node>>,
    data: String,
}


impl Node {
    fn new(_data: String) -> Node {
        Node {
            data : _data.clone(),
            left : None,
            right : None,
        }
    }

    fn insert_left(&mut self, mut node: &Rc<Node>) {
        self.left = Some(node.clone());
    }

    fn insert_right(&mut self, mut node: &Rc<Node>) {
        self.left = Some(node.clone());
    }
}

fn main() {
    let mut root = Rc::new(Node::new(String::from("root")));
    let mut left = Rc::new(Node::new(String::from("left")));
    root.insert_left(&left);
}
Run Code Online (Sandbox Code Playgroud)

我有编译错误:

error: cannot borrow immutable borrowed content as mutable
  --> so.rs:31:9
   |
31 |         root.insert_left(&left);
   |         ^^^^

error: aborting due to previous error
Run Code Online (Sandbox Code Playgroud)

我无法理解这里有什么问题.经过一些尝试错误的迭代,我发现问题在于insert_left()函数:if self是一个不可变的引用,然后它用注释掉的内容编译,但是一个不可变的引用不允许我完成我的目标.

She*_*ter 7

这是你问题的MCVE:

use std::rc::Rc;

struct Node;

impl Node {
    fn insert_left(&mut self) {}
}

fn main() {
    let root = Rc::new(Node);
    root.insert_left();
}
Run Code Online (Sandbox Code Playgroud)

您可以通过删除尽可能多的代码同时仍然得到相同的错误来达到这样的示例.这个过程有助于建立对问题的理解.

问题是Rc不允许任何类型的突变.如文档中所述:

Rust中的共享指针默认情况下禁止突变,Rc也不例外.如果你需要变异Rc,请使用CellRefCell.

因此,没有办法从a Rc<Foo>转到a &mut Foo,这需要调用该insert_left方法.

如文档所述,您可以使用允许内部可变性的类型之一,例如a CellRefCell.这些函数有点像互斥体,但对多线程场景无效.它们确保一次只能提供一个值的可变引用,这是Rust安全性的关键组成部分.

如果你不需要Rc共享的功能,你也可以转向拥有它Option<Box<Node>>.