Brief:我是Rust的新手,所以我决定通过实现一个双向链表来练习.出于调试目的,我实现了get()方法,但未能将值从Rc<RefCell<_>>中复制出来.(很抱歉问了这么愚蠢的问题)

Problem:我try 在.get()中返回Result<T, &'static str>,其中T是 node 中存储的数据类型,&str是错误消息字符串.borrow 判断器告诉我不能返回对方法内变量的引用,所以我try 将内部值复制出来并返回它,但失败了.

Source code:

use std::{rc::Rc, cell::RefCell};

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

impl<T> Node<T> {
    /// Instantiate a new dummy node.
    /// This node is used to mark the start and end of the list.
    /// It is not counted in the size of the list.
    fn new() -> Self {
        Node {
            data: None,
            prev: None,
            next: None,
        }
    }
    /// Instantiate a new content node.
    /// This node is used to store data.
    /// It is counted in the size of the list.
    fn from(data: T) -> Self {
        Node {
            data: Some(data),
            prev: None,
            next: None,
        }
    }
}

struct List<T> {
    head: Rc<RefCell<Node<T>>>,
    tail: Rc<RefCell<Node<T>>>,
    size: usize,
}

impl<T> List<T> {
    pub fn new() -> Self {
        let head = Rc::new(RefCell::new(Node::new()));
        let tail = Rc::new(RefCell::new(Node::new()));
        head.borrow_mut().next = Some(Rc::clone(&tail));
        tail.borrow_mut().prev = Some(Rc::clone(&head));
        List { head, tail, size: 0 }
    }
    pub fn prepend(&self, data: T) {
        let node = Rc::new(RefCell::new(Node::from(data)));
        let mut head = self.head.borrow_mut();
        
        node.borrow_mut().next = Some(head.next.take().unwrap());
        node.borrow_mut().prev = Some(Rc::clone(&self.head));
        head.next = Some(Rc::clone(&node));
        if let Some(next) = node.borrow().next.as_ref() {
            next.borrow_mut().prev = Some(Rc::clone(&node));
        };
    }
    pub fn append(&self, data: T) {
        let node = Rc::new(RefCell::new(Node::from(data)));
        let mut tail = self.tail.borrow_mut();
        
        node.borrow_mut().prev = Some(Rc::clone(&tail.prev.take().unwrap()));
        node.borrow_mut().next = Some(Rc::clone(&self.tail));
        tail.prev = Some(Rc::clone(&node));
        if let Some(prev) = node.borrow().prev.as_ref() {
            prev.borrow_mut().next = Some(Rc::clone(&node));
        };
    }
    pub fn get(&self, index: isize) -> Result<T, &'static str> {
        let mut current: Rc<RefCell<Node<T>>> = Rc::clone(self.head.borrow().next.as_ref().unwrap());
        for _ in 0..index {
            let tmp = Rc::clone(current.borrow().next.as_ref().ok_or("Index out of range")?);
            current = tmp;
        }
        let result = current.borrow().data.as_ref().ok_or("Index out of range")?;  // error[E0716]
        Ok(*result)  // error[E0507]
    }
}
/*
error[E0716]: temporary value dropped while borrowed
  --> src\linked.rs:74:22
   |
74 |         let result = current.borrow().data.as_ref().ok_or("Index out of range")?;
   |                      ^^^^^^^^^^^^^^^^                                           - temporary value is freed at the end of this statement
   |                      |
   |                      creates a temporary value which is freed while still in use
75 |         Ok(*result)
   |            ------- borrow later used here
   |
help: consider using a `let` binding to create a longer lived value
   |
74 ~         let binding = current.borrow();
75 ~         let result = binding.data.as_ref().ok_or("Index out of range")?;
   |

error[E0507]: cannot move out of `*result` which is behind a shared reference
  --> src\linked.rs:75:12
   |
75 |         Ok(*result)
   |            ^^^^^^^ move occurs because `*result` has type `T`, which does not implement the `Copy` trait
*/

I've Tried:

Also:我可能做错了这些,如果其中一个帖子解决了我的问题,但我没有正确地执行,请原谅我,并请教我如何正确地执行它.非常感谢.

推荐答案

这对我来说很管用:

    pub fn get(&self, index: isize) -> Result<T, &'static str>
        where T: Clone
    {
        let mut current: Rc<RefCell<Node<T>>> = Rc::clone(self.head.borrow().next.as_ref().unwrap());
        for _ in 0..index {
            let tmp = Rc::clone(current.borrow().next.as_ref().ok_or("Index out of range")?);
            current = tmp;
        }
        let guard = current.borrow();
        guard.data.clone().ok_or("Index out of range")
    }

(playground link)

您需要第where T: Clone行来启用.clone()方法.


有人说,为了学习Rust而实现双向链表是错误的……我很抱歉地报告他们是对的.当我开始的时候,我也做了同样的事情.我try 的另一件事是编写光线跟踪器;这件事做得好多了.

核心数据 struct 是使用原始指针实现的.这意味着编写不安全的代码,并在其周围放置一个安全的API:一种高级的Rust技能.

Rust相关问答推荐

有没有方法处理rust中嵌套的ok_or()?

在一个tauri协议处理程序中调用一个rectuc函数的推荐技术是什么?

收集RangeInclusive T到Vec T<><>

如果死 struct 实现了/派生了一些特征,为什么Rust会停止检测它们?

无符号整数的Rust带符号差

这个不安全的 Rust 代码有什么问题,所以它可以在 Windows 上运行,但不能在 Ubuntu 上运行?

如何使用tracing-subscriberRust crate 构建多编写者、全局过滤订阅者

在 Rust 中,在第一个空格上分割字符串一次

如何限制 GtkColumnView 行数

需要一个有序向量来进行 struct 初始化

当没有实际结果时,如何在 Rust 中强制执行错误处理?

Rust Redis 中的 HSET 命令问题

具有在宏扩展中指定的生命周期的枚举变体数据类型

如何在 Rust 中将 UTF-8 十六进制值转换为 char?

仅在运行测试时生成调试输出

返回引用字符串的future

有没有办法在 Rust 中对 BigInt 进行正确的位移?

如何断言代码不会在测试中编译?

你能用 Rust 和 winapi 制作 Windows 桌面应用程序吗?

如何从 Rust 中不同类型的多个部分加入 Path?