我正在编写一个 fn 来从 LinkedList 中的最后一个 pos 中弹出元素,但是在这种情况下会发生双 mut ref 错误,我试图获取倒数第二个节点,以便我可以砍掉尾部
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
if next.next.is_none() {
break;
}
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
但是代码在没有检查的情况下编译
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
// if next.next.is_none() {
// break;
// }
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
error[E0499]: cannot borrow `curr.next` as mutable more than once at a time
--> src\main.rs:70:29
|
62 | while let Some(ref mut next) = curr.next {
| ------------ first mutable borrow occurs here
...
70 | let taken = curr.next.take();
| ^^^^^^^^^^^^^^^^
| |
| second mutable borrow occurs here
| first borrow later used here
似乎无法弄清楚这个问题,因为我是 Rust 新手。任何帮助将不胜感激。
use std::fmt::Debug;
#[derive(Debug)]
struct Node<T> {
data: T,
next: Option<Box<Node<T>>>,
}
#[derive(Debug)]
struct LinkedList<T> {
head: Option<Box<Node<T>>>,
len: usize,
}
impl<T: Debug> LinkedList<T> {
fn new() -> Self {
Self { head: None, len: 0 }
}
fn push(&mut self, data: T) {
match self.head {
None => self.head = Some(Box::new(Node::new(data))),
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
curr = next;
}
curr.next = Some(Box::new(Node::new(data)));
}
}
self.len += 1;
}
// head -> 1 -> 2
fn pop(&mut self) -> Option<T> {
match self.head {
None => None,
Some(ref mut head) => {
let mut curr = head;
while let Some(ref mut next) = curr.next {
// if next.next.is_none() {
// break;
// }
curr = next;
}
let taken = curr.next.take();
taken.map(|x| x.data)
}
}
}
}
impl<T> Node<T> {
fn new(data: T) -> Self {
Node { data, next: None }
}
}
这是借用检查器的一个众所周知的缺陷。您的代码可以使用下一代 Polonius 借用检查器进行编译。
解决此问题的方法是不在循环中保留可变引用:
while curr.next.is_some() {
curr = curr.next.as_mut().unwrap();
}
这既尴尬又丑陋,但这就是我们现在能做的。