我刚刚开始使用Ruust,并试图实现一些简单的数据 struct .我在双向链表的迭代器上收到以下错误,我不明白为什么会发生这种情况.

use std::cell::RefCell;
use std::rc::Rc;

struct Node<T> {
    value: T,
    next: Option<Rc<RefCell<Node<T>>>>,
    prev: Option<Rc<RefCell<Node<T>>>>,
}

impl<T> Node<T> {
    fn new(value: T) -> Rc<RefCell<Self>> {
        Rc::new(RefCell::new(Node {
            value,
            next: None,
            prev: None,
        }))
    }
}

pub struct DoublyLinkedList<T> {
    head: Option<Rc<RefCell<Node<T>>>>,
    tail: Option<Rc<RefCell<Node<T>>>>,
    len: usize,
}

impl<T> DoublyLinkedList<T> {
    pub fn new() -> Self {
        DoublyLinkedList {
            head: None,
            tail: None,
            len: 0,
        }
    }

    pub fn len(&self) -> usize {
        self.len
    }

    pub fn is_empty(&self) -> bool {
        self.len == 0
    }

    pub fn push_front(&mut self, value: T) {
        let new_node = Node::new(value);
        match self.head.take() {
            Some(old_head) => {
                old_head.borrow_mut().prev = Some(new_node.clone());
                new_node.borrow_mut().next = Some(old_head);
                self.head = Some(new_node);
            }
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        }
        self.len += 1;
    }

    pub fn push_back(&mut self, value: T) {
        let new_node = Node::new(value);
        match self.tail.take() {
            Some(old_tail) => {
                old_tail.borrow_mut().next = Some(new_node.clone());
                new_node.borrow_mut().prev = Some(old_tail);
                self.tail = Some(new_node);
            }
            None => {
                self.head = Some(new_node.clone());
                self.tail = Some(new_node);
            }
        }
        self.len += 1;
    }

    pub fn pop_front(&mut self) -> Option<T> {
        self.head.take().map(|old_head| {
            match old_head.borrow_mut().next.take() {
                Some(new_head) => {
                    new_head.borrow_mut().prev = None;
                    self.head = Some(new_head);
                }
                None => {
                    self.tail = None;
                }
            }
            self.len -= 1;
            Rc::try_unwrap(old_head).ok().unwrap().into_inner().value
        })
    }

    pub fn pop_back(&mut self) -> Option<T> {
        self.tail.take().map(|old_tail| {
            match old_tail.borrow_mut().prev.take() {
                Some(new_tail) => {
                    new_tail.borrow_mut().next = None;
                    self.tail = Some(new_tail);
                }
                None => {
                    self.head = None;
                }
            }
            self.len -= 1;
            Rc::try_unwrap(old_tail).ok().unwrap().into_inner().value
        })
    }

    pub fn iter(&self) -> Iter<T> {
        Iter {
            next: self.head.as_ref().map(|node| node.clone()),
        }
    }
}

pub struct Iter<T> {
    next: Option<Rc<RefCell<Node<T>>>>,
}

impl<T> Iterator for Iter<T> {
    type Item = T;

    fn next(&mut self) -> Option<Self::Item> {
        self.next.take().map(|node| {
            self.next = node
                .borrow()
                .next
                .as_ref()
                .map(|next_node| next_node.clone());
            node.borrow().value
            // Rc::try_unwrap(node).ok().unwrap().into_inner().value
        })
    }
}


我本以为借入将能够提取RefCell的内部值,但我收到以下错误:

cannot move out of dereference of `Ref<'_, Node<T>>`

node.borrow().value
move occurs because value has type `T`, which does not implement the `Copy` trait

然而,下面注释掉的代码可以工作.

推荐答案

RefCell::borrow()返回一个Ref<Node>,它实现Deref<Target = Node>,这给你一个&Node引用,这允许你从它读取,但不会改变它or move it out.

node.borrow().value试图移出Node struct 的域value的内容.如果只有&Node访问权限,则无法做到这一点.

作为《铁 rust 》中的一般原则:

  • 如果你有&T,你可以从T开始读.一百零二
  • 如果你有&mut T个,那么你可以阅读T,也可以对T进行Mutations ;而且你可以移出T,但前提是你换了一个替代者(与std::mem::swap或它的一个亲戚).
  • 如果你有T个,那么你可以做&mut T允许的任何事情,也可以搬出go without个替换.

为了在没有替换的情况下将值移出RefCell,您的

Rc::try_unwrap(node).ok().unwrap().into_inner().value

才是正确的做法;解构包装器,直到获得值为止.许多Rust类型将有into_inner()风格的方法,正是这样才有可能发生这种事情.

Rust相关问答推荐

基于对vec值的引用从该值中删除该值

异步FN中的 rust 递归

integer cast as pointer是什么意思

定义只有一些字段可以缺省的 struct

如何将单个 struct 实例与插入器一起传递到Rust中的映射

无法将 rust 蚀向量附加到另一个向量

对于rustc编译的RISC-V32IM二进制文件,llvm objdump没有输出

Rust面向对象设计模式

为什么 Rust 创建的 f32 小于 f32::MIN_POSITIVE?

std mpsc 发送者通道在闭包中使用时关闭

decltype、dyn、impl traits,重构时如何声明函数的返回类型

使用 lalrpop 在 rust 中解析由 " 引用的字符串

在给定 Rust 谓词的情况下,将 Some 转换为 None 的惯用方法是什么?

不安全块不返回预期值

Some(v) 和 Some(&v) 有什么区别?

哪些特征通过 `Deref` 而哪些不通过?

如何在 Rust 中编写修改 struct 的函数

如何将切片推入数组?

Rust:为什么在 struct 中borrow 引用会borrow 整个 struct?

在同一向量 Rust 中用另一个字符串扩展一个字符串