【问题标题】:Cannot borrow immutable borrowed content as mutable when implementing a binary tree with Rc使用 Rc 实现二叉树时,不能将不可变的借用内容借用为可变的
【发布时间】:2016-12-08 17:08:05
【问题描述】:

我想实现一棵二叉树。我的主要语言是 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() 函数中:如果self 是不可变引用,那么它会使用注释掉的内容进行编译,但不可变引用不允许我实现目标。

【问题讨论】:

  • 你看过23 other questions with the same error message吗? this 问题与其他问题有何不同?甚至还有一个标题为Changing a node in a tree in Rust,看起来非常相关。大量的effort is expected from question askers,至少找到具有相同错误消息和数据结构的其他问题似乎是最低限度的。
  • 对于惯用的 Rust,你不应该调用你的变量_data。前导下划线用于表示未使用的变量。该变量非常常用。
  • @Shepmaster 构造函数的输入参数的更好约定是什么?
  • 总的来说,Rust 中的变量阴影没有什么问题。但是,这里没有出现阴影;只需调用它data 就可以了。请记住,当用户浏览您的文档时,该名称也会向用户显示

标签: rust


【解决方案1】:

这是您的问题的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

默认情况下,Rust 中的共享指针不允许突变,Rc 也不例外。如果您需要通过Rc 进行变异,请使用CellRefCell

因此,没有办法从Rc&lt;Foo&gt; 转到&amp;mut Foo,这需要调用insert_left 方法。

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

如果您不需要Rc 的分享功能,您也可以换成Option&lt;Box&lt;Node&gt;&gt;

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-05-17
    • 2018-07-05
    • 2015-09-14
    相关资源
    最近更新 更多