Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 如何打开由弱::升级获得的具有多个强引用的Rc?_Rust - Fatal编程技术网

Rust 如何打开由弱::升级获得的具有多个强引用的Rc?

Rust 如何打开由弱::升级获得的具有多个强引用的Rc?,rust,Rust,我正在尝试实现一个链表以便于学习,现在我正在实现的一个功能是fn pop_back,它将数据弹出到链表实例的最后一个位置。RefCell、Rc和WEBLE主要用于将数据存储到列表中 这是我的代码(fn pop_back位于代码底部): 使用std::cell::RefCell; 使用std::rc::{rc,弱}; #[导出(调试)] 发布结构DbNode{ 数据:T, 下一步:选择, 上:期权, } #[导出(调试)] 发布结构数据库列表{ 第一:选择, 最后:选择,, } impl数据库列表

我正在尝试实现一个链表以便于学习,现在我正在实现的一个功能是fn pop_back,它将数据弹出到链表实例的最后一个位置。RefCell、Rc和WEBLE主要用于将数据存储到列表中

这是我的代码(fn pop_back位于代码底部):

使用std::cell::RefCell;
使用std::rc::{rc,弱};
#[导出(调试)]
发布结构DbNode{
数据:T,
下一步:选择,
上:期权,
}
#[导出(调试)]
发布结构数据库列表{
第一:选择,
最后:选择,,
}
impl数据库列表{
pub fn new()->Self{
数据库列表{
第一:没有,
最后:没有,
}
}
发布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_front(&mut self)->选项{
匹配self.first.take(){
一些(首先)=>{
匹配Rc::try_unwrap(第一个){
正常(参考文献)=>{
让inner=refc.into_inner();
self.first=inner.next;
如果让None=self.first{
self.last=无;
};
一些(内部数据)
},
Err()=>无,
}
},
无=>无,
}
}
pub fn pop_back(&mut self)->选项{
匹配self.last.take(){
一些(最后)=>{
//todo:try_unwrap出错:保存此引用的“last”中的“prev”?
匹配Rc::try_unwrap(弱::升级(&last).unwrap()){
正常(参考文献)=>{
让inner=refc.into_inner();
self.last=inner.prev;
一些(内部数据)
},
Err()=>无,
}
},
无=>无,
}
}
}
如果可能,fn pop_back应返回最后一个DbNode,并将现有“last”的前一个DbNode中的“next”DbNode设置为“new last”。因此,我需要展开现有的DbNode以获得上一个DbNode,它将是新的最后一个。但是Rc::try_unwrap会出错。我猜这是因为现有的last本身是一个弱引用,因此它已经有一个强引用,并且引用计数随着Rc::try\u unwrap(弱::升级(&last).unwrap())的增加而增加。我不是100%肯定我的猜测

我该怎么办

完整的 我是根据@masklin建议的方法来做这件事的。除此之外,在Rc::try_unwrap之前,当列表只剩下一个DbNode时,我只需删除DbList中“first”字段保留的Rc,因为当列表中只剩下一个DbNode时,“prev”字段具有None。它遇到了与我第一次遇到的相同的错误,但没有删除“first”

以下是fn pop_back的最终代码:

pub fn pop_back(&mut self) -> Option<T> {
    match self.last.take() {
        Some(last) => {
            let last = Weak::upgrade(&last).unwrap();
            if Rc::ptr_eq(self.first.as_ref().unwrap(), &last) {
                self.first = None;
            } else {
                let prev = Weak::upgrade(last.borrow().prev.as_ref().unwrap());
                prev.as_ref().unwrap().borrow_mut().next = None;
                self.last = Some(Rc::downgrade(prev.as_ref().unwrap()));                  
            }
            match Rc::try_unwrap(last) {
                Ok(iv) => Some(iv.into_inner().data),
                Err(_) => None,
            }                  
        },
        None => None,
    }
}
pub fn pop_back(&mut self)->选项{
匹配self.last.take(){
一些(最后)=>{
让last=Weak::升级(&last).unwrap();
if Rc::ptr_eq(self.first.as_ref().unwrap(),&last){
self.first=无;
}否则{
让prev=Weak::upgrade(last.borrow().prev.as_ref().unwrap());
prev.as_ref().unwrap().borrow_mut().next=无;
self.last=Some(Rc::降级(prev.as_ref().unwrap());
}
匹配Rc::try_unwrap(最后一个){
Ok(iv)=>一些(iv.进入内部()数据),
Err()=>无,
}                  
},
无=>无,
}
}
我猜这是因为现有的last本身是一个弱引用,所以它已经有一个强引用,并且引用计数增加了

这种使用弱引用的方案真的很奇怪(这并不是它们真正的目的),但这里您需要做的是:

  • 摘自上一篇
  • 升级last(),创建第二个Rc
  • 跟随它的prev()链接到倒数第二个
  • 设置为新的最后一个
  • 从第二个到最后一个,这是第一个/现有的Rc
  • 删除升级值或从第二个到最后一个的值,它们都是强引用
    pub fn pop_back(&mut self) -> Option<T> {
        match self.last.take() {
            Some(last) => {
                let last = Weak::upgrade(&last).unwrap();
                if Rc::ptr_eq(self.first.as_ref().unwrap(), &last) {
                    self.first = None;
                } else {
                    let prev = Weak::upgrade(last.borrow().prev.as_ref().unwrap());
                    prev.as_ref().unwrap().borrow_mut().next = None;
                    self.last = Some(Rc::downgrade(prev.as_ref().unwrap()));                  
                }
                match Rc::try_unwrap(last) {
                    Ok(iv) => Some(iv.into_inner().data),
                    Err(_) => None,
                }                  
            },
            None => None,
        }
    }