提问人:Danilo Souza Morães 提问时间:12/28/2022 更新时间:12/28/2022 访问量:329
不能借用为可变的,从借用的值 [duplicate] 获取可变引用
Cannot borrow as mutable, getting a mutable reference from a borrowed value [duplicate]
问:
我正在关注另一篇文章:了解 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);
}
答:
接受的答案可以编译,但不起作用,因为它不会向根目录添加节点。
你是对的,并修复原始解决方案,这里有一个正确添加根节点的版本:
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(¤t_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_mut() 我得到的值是一个私有字段,所以我是 假设我无法访问包含值的任何属性,如果是 可变引用?
不是真的,这里发生的事情是你没有调用返回 的函数,你实际上是在调用返回的函数。通过访问,您正在尝试从 而不是 访问私有字段。RefCell::borrow_mut
RefMut<Node>
<Rc as BorrowMut>::borrow_mut
&mut RefMut<...>
value
value
RefCell
Node
请注意,在我的实现中,我显式调用了 ,这解决了这个问题。RefCell::borrow_mut
评论
RefCell::borrow_mut
Ref/RefMut
&mut current_node.left
评论
BorrowMut
BorrowMut::borrow_mut
RefCell::borrow_mut
Rc<RefCell<T>>
Box<T>