我想实现二叉树。我的主要语言是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);
}
我有编译错误:
error: cannot borrow immutable borrowed content as mutable
--> so.rs:31:9
|
31 | root.insert_left(&left);
| ^^^^
error: aborting due to previous error
我无法理解这里有什么问题。经过一些尝试错误的迭代后,我发现问题出在insert_left()
函数中:if self
是一个不可变引用,然后用注释掉的内容编译,但是一个不可变的引用不允许我完成我的目标。
答案 0 :(得分: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();
}
您可以通过删除尽可能多的代码同时仍然获得相同的错误来达到这样的示例。这个过程有助于建立对问题的理解。
问题是Rc
不允许任何类型的突变。正如stated in the documentation:
因此,无法从Rc<Foo>
转到&mut Foo
,这需要调用insert_left
方法。
如文档所述,您可以使用允许内部可变性的其中一种类型,例如Cell
或RefCell
。这些函数有点像互斥体,但对多线程场景无效。他们确保一次只能提供一个值的可变引用,这是Rust安全的关键组成部分。
如果您不需要Rc
分享的功能,您也可以转而使用Option<Box<Node>>
。