Rust 如何使用Rc<;的数据类型;RefCell<;T>&燃气轮机;在结构中?
我正在尝试实现一个用于学习目的的链表。std::cell::RefCell和stc::rc:{rc,Weak}主要用于将数据存储到列表实例中。现在我正在实现fnpop,它使用并返回列表中第一个位置的值,但我不知道如何使用用Rc和RefCell包装的值 这是我的密码:Rust 如何使用Rc<;的数据类型;RefCell<;T>&燃气轮机;在结构中?,rust,Rust,我正在尝试实现一个用于学习目的的链表。std::cell::RefCell和stc::rc:{rc,Weak}主要用于将数据存储到列表实例中。现在我正在实现fnpop,它使用并返回列表中第一个位置的值,但我不知道如何使用用Rc和RefCell包装的值 这是我的密码: use std::cell::RefCell; use std::rc::{Rc, Weak}; #[derive(Debug)] pub struct DbNode<T> { data: T, nex
use std::cell::RefCell;
use std::rc::{Rc, Weak};
#[derive(Debug)]
pub struct DbNode<T> {
data: T,
next: Option<Rc<RefCell<DbNode<T>>>>,
prev: Option<Weak<RefCell<DbNode<T>>>>,
}
#[derive(Debug)]
pub struct DbList<T> {
first: Option<Rc<RefCell<DbNode<T>>>>,
last: Option<Weak<RefCell<DbNode<T>>>>,
}
pub fn push_front(&mut self, data: T) {
match self.first.take() {
Some(e) => {
let new_front = Rc::new(RefCell::new(DbNode {
data,
next: Some(e.clone()),
prev: None,
}));
let mut me = e.borrow_mut();
me.prev = Some(Rc::downgrade(&new_front));
self.first = Some(new_front);
},
None => {
let new_data = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: None,
}));
self.last = Some(Rc::downgrade(&new_data));
self.first = Some(new_data);
},
}
}
pub fn push_back(&mut self, data: T) {
match self.last.take() {
Some(l) => {
let new_back = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: Some(l.clone()),
}));
let st = Weak::upgrade(&l).unwrap();
let mut ml = st.borrow_mut();
self.last = Some(Rc::downgrade(&new_back));
ml.next = Some(new_back);
},
None => {
let new_data = Rc::new(RefCell::new(DbNode {
data,
next: None,
prev: None,
}));
self.last = Some(Rc::downgrade(&new_data));
self.first = Some(new_data);
},
}
}
pub fn pop(&mut self) -> Option<T> {
match self.first.take() {
Some(f) => {
// How can I??
// let result = Some(f.into_inner().data);
// result
},
None => None,
}
}
使用std::cell::RefCell;
使用std::rc::{rc,弱};
#[导出(调试)]
发布结构DbNode{
数据:T,
下一步:选择,
上:期权,
}
#[导出(调试)]
发布结构数据库列表{
第一:选择,
最后:选择,,
}
发布fn推送前(和多个自身,数据:T){
匹配self.first.take(){
一些(e)=>{
让new_front=Rc::new(RefCell::new(DbNode{
数据,
下一步:一些(如克隆()),
上一篇:没有,
}));
让我们共同学习;
me.prev=Some(Rc::降级(&new_front));
self.first=一些(新的前);
},
无=>{
让new_data=Rc::new(RefCell::new(DbNode{
数据,
下一个:没有,
上一篇:没有,
}));
self.last=Some(Rc::降级(&new_数据));
self.first=一些(新的_数据);
},
}
}
发布fn推回(&mut self,数据:T){
匹配self.last.take(){
一些(l)=>{
让new_返回=Rc::new(RefCell::new(DbNode{
数据,
下一个:没有,
prev:Some(l.clone()),
}));
让st=Weak::upgrade(&l).unwrap();
设mut ml=st.borrow_mut();
self.last=Some(Rc::降级(&new_back));
ml.next=Some(新返回);
},
无=>{
让new_data=Rc::new(RefCell::new(DbNode{
数据,
下一个:没有,
上一篇:没有,
}));
self.last=Some(Rc::降级(&new_数据));
self.first=一些(新的_数据);
},
}
}
pub fn pop(&mut self)->选项{
匹配self.first.take(){
一些(f)=>{
//我怎么能??
//让结果=一些(f.进入_inner().数据);
//结果
},
无=>无,
}
}
我想要实现的是返回structDbNode中位于structDbList的“first”中的内部“data”值,并将None设置为要使用的数据所在的“first”,如果“next”是None,则将“next”设置为“first”。
起初,我尝试使用Rc::downcast使用内部值,但匹配块中的“f”类型是“RefCell”,而不是“Rc”,然后我尝试使用RefCell::into_inner(),但编译器说:
无法移出Rc
发生移动是因为值的类型为std::cell::RefCell
,而该类型不实现Copy
特性
我完全理解这意味着什么,但我不知道我该怎么做。正确的方法是什么???你很接近。使用:
如果Rc
正好有一个强引用,则返回内部值。否则,返回的Err
与传入的Rc
相同。即使存在突出的弱引用,这也会成功
pub-fn-pop(&mut-self)->选项{
匹配self.first.take(){
一些(f)=>{
匹配Rc::尝试展开(f){
正常(参考单元格)=>{
//您可以在此处执行refcell.into_inner
一些(refcell.into_inner().data)
},
错误(41;)=>{
//另一个Rc仍然存在,因此您无法获得该值的所有权
没有一个
}
}
},
无=>无,
}
}
很有效,非常感谢!我还有一个问题:如何在选项匹配中获得Rc而不是RefCell?据我所知,它是RefCell,因为它是自动取消引用的。如果我想得到Rc,我能做些什么呢?@parksheolu我不明白,在这个示例中,f
是一个Rc
。真的吗?如果是这样,我的VisualStudio很奇怪。当我在“f”之后键入dot时,IDE会显示RefCell的方法列表,而不是Rc…这是由于取消引用,f
是一个Rc
,但是Rc
s实现了Deref
的内部值,提供了对字段和方法的直接访问。这是由编译器透明地完成的。这也用于Box
s,甚至Vec
s。我知道了。你说得对。我刚刚检查了Rc::try_unwrap in docs,它只接受Rc。所以,“f
是Rc,我可以将它视为Rc和它的内部值,因为Deref
”是正确的吗?
pub fn pop(&mut self) -> Option<T> {
match self.first.take() {
Some(f) => {
match Rc::try_unwrap(f) {
Ok(refcell) => {
// you can do refcell.into_inner here
Some(refcell.into_inner().data)
},
Err(_) => {
// another Rc still exists so you cannot take ownership of the value
None
}
}
},
None => None,
}
}