繁体   English   中英

如何使用 Rc 的数据类型<refcell<t> &gt; 在结构中? </refcell<t>

[英]How can I consume data type of Rc<RefCell<T>> in struct?

我正在尝试实现一个用于学习目的的链接列表。 std::cell::RefCell 和 stc::rc::{Rc, Weak} 主要用于将数据存储到列表实例中。 现在我正在实现fn pop ,它在列表的第一个位置使用并返回一个值,但我不知道如何使用用 Rc 和 RefCell 包装的值。

这是我的代码:

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,
    }
}

我想要实现的是返回结构 DbNode 中位于 struct DbList中“第一个”中的内部“数据”值,并将None设置为“第一个”,如果“下一个”为None则要消耗的数据位于该第一个,否则将“下一个”设置为“第一个”。 起初,我尝试使用Rc::downcast来消耗内部值,但匹配块中 'f' 的类型是 'RefCell',而不是 'Rc',然后我尝试使用 RefCell::into_inner(),但是编译器说:

无法移出Rc移动,因为 value 的类型为std::cell::RefCell<ds::dll::DbNode<T>> ,它没有实现Copy trait

我完全理解这意味着什么,但我不知道我应该怎么做。 正确的做法是什么??

你很亲密。 使用Rc::try_unwrap()

如果Rc恰好有一个强引用,则返回内部值。 否则,将返回带有传入相同RcErr 。即使存在未完成的弱引用,这也会成功。

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,
    }
}

如何创建 Rc <refcell< to something that already exists?< div><div id="text_translate"><p> 因此,为了自学一些 Rust,我决定创建一个我喜欢的简单混合数据类型 ChainVec。 这是一个向量的双向链接列表,如果您需要调整可能增长到巨大规模的向量的大小,这很有用。 它使用链表逻辑,但查找、搜索和迭代特性要快得多,因为它们的增长时间为 O(n/alot)。 不过,这并不是重点:我遇到的问题会出现在任何双向链表中。</p><p> 这就是问题所在......在 C 中,当我创建新的链表节点时,我可以将其“尾部”设置为指向前一个节点的指针。 我可以在 C 中像糖果一样扔指针,但在 Rust 中,我还不知道如何创建新指针。 这是我尝试过的...(在 fn push_head 下查找无效行)</p><p> 注意:在我的实现中,chainvec 的“头”节点是您选择指向的任何一个,因此列表头/尾没有单独的结构。</p><pre> #[allow(non_snake_case)] use std::{cell::RefCell, rc::Rc}; #[allow(dead_code)] struct ChainVec&lt;T&gt; { item: Option&lt;Vec&lt;T&gt;&gt;, head: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, tail: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, } impl&lt;T&gt; ChainVec&lt;T&gt; { fn new(prealloc: usize) -&gt; Self { let vector: Vec&lt;T&gt; = Vec::with_capacity(prealloc); Self { item: Some(vector), head: None, tail: None, } } fn new_with_links(prealloc: usize, head: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, tail: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;) -&gt; Self { let vector: Vec&lt;T&gt; = Vec::with_capacity(prealloc); Self { item: Some(vector), head: head, tail: tail, } } fn push_head(&amp;mut self, prealloc: usize) { self.head = Some(Rc::new(RefCell::new(ChainVec::new_with_links(prealloc, None, Some(Rc::new(RefCell::new(self))))))); } } #[allow(unused_variables)] fn main() { let alef: ChainVec&lt;u32&gt; = ChainVec::new(100); println,("Hello; world!"); }</pre><p> 显然,当我尝试通过 Some(Rc::new(RefCell::new(self))) 在 push_head 中创建一个新指针时,我迷路了。 我有</p><pre>mismatched types expected struct `ChainVec&lt;T&gt;` found mutable reference `&amp;mut ChainVec&lt;T&gt;`</pre><p> 取消引用运算符在这里不做任何事情......我不知道如何继续。</p><p> 如何创建对已经存在的结构的 Rc&lt;RefCell&lt; 引用? </p></div></refcell<>

[英]How can I create an Rc<RefCell< to something that already exists?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何为包含Rc的结构实现Deref <Refcell<Trait> &gt;? 将RefCell和Rc包装为结构类型 如何迭代遍历用 Rc 构建的树<refcell<t> &gt; 同时在枚举上可变匹配? </refcell<t> 如何从 Rc 获得 &amp;A 参考<RefCell<A> &gt;? 如何创建 Rc <refcell< to something that already exists?< div><div id="text_translate"><p> 因此,为了自学一些 Rust,我决定创建一个我喜欢的简单混合数据类型 ChainVec。 这是一个向量的双向链接列表,如果您需要调整可能增长到巨大规模的向量的大小,这很有用。 它使用链表逻辑,但查找、搜索和迭代特性要快得多,因为它们的增长时间为 O(n/alot)。 不过,这并不是重点:我遇到的问题会出现在任何双向链表中。</p><p> 这就是问题所在......在 C 中,当我创建新的链表节点时,我可以将其“尾部”设置为指向前一个节点的指针。 我可以在 C 中像糖果一样扔指针,但在 Rust 中,我还不知道如何创建新指针。 这是我尝试过的...(在 fn push_head 下查找无效行)</p><p> 注意:在我的实现中,chainvec 的“头”节点是您选择指向的任何一个,因此列表头/尾没有单独的结构。</p><pre> #[allow(non_snake_case)] use std::{cell::RefCell, rc::Rc}; #[allow(dead_code)] struct ChainVec&lt;T&gt; { item: Option&lt;Vec&lt;T&gt;&gt;, head: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, tail: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, } impl&lt;T&gt; ChainVec&lt;T&gt; { fn new(prealloc: usize) -&gt; Self { let vector: Vec&lt;T&gt; = Vec::with_capacity(prealloc); Self { item: Some(vector), head: None, tail: None, } } fn new_with_links(prealloc: usize, head: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;, tail: Option&lt;Rc&lt;RefCell&lt;ChainVec&lt;T&gt;&gt;&gt;&gt;) -&gt; Self { let vector: Vec&lt;T&gt; = Vec::with_capacity(prealloc); Self { item: Some(vector), head: head, tail: tail, } } fn push_head(&amp;mut self, prealloc: usize) { self.head = Some(Rc::new(RefCell::new(ChainVec::new_with_links(prealloc, None, Some(Rc::new(RefCell::new(self))))))); } } #[allow(unused_variables)] fn main() { let alef: ChainVec&lt;u32&gt; = ChainVec::new(100); println,("Hello; world!"); }</pre><p> 显然,当我尝试通过 Some(Rc::new(RefCell::new(self))) 在 push_head 中创建一个新指针时,我迷路了。 我有</p><pre>mismatched types expected struct `ChainVec&lt;T&gt;` found mutable reference `&amp;mut ChainVec&lt;T&gt;`</pre><p> 取消引用运算符在这里不做任何事情......我不知道如何继续。</p><p> 如何创建对已经存在的结构的 Rc&lt;RefCell&lt; 引用? </p></div></refcell<> Rust 无法修改 Rc 中的 RefCell 与 Rc 匹配<RefCell<T> &gt; 向下转换 Rc <refcell<box<struct> &gt;&gt; 到 Rc <refcell<box<dyn trait> &gt;&gt; </refcell<box<dyn></refcell<box<struct> 参考单元<refcell<> &gt; 不会改变 我如何通过Rc <RefCell<Box<MyStruct> &gt;&gt;接受Rc的功能 <RefCell<Box<dyn MyTrait> &gt;&gt;?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM