Rust链表疑问

在解 leetcode 203. 移除链表元素 时,遇到一些生命周期和引用,再借用的一些疑问,此题非常简单,就是要删除给定数值的节点。先贴出来解法代码:

// Definition for singly-linked list.
// #[derive(PartialEq, Eq, Clone, Debug)]
// pub struct ListNode {
//   pub val: i32,
//   pub next: Option<Box<ListNode>>
// }
// 
// impl ListNode {
//   #[inline]
//   fn new(val: i32) -> Self {
//     ListNode {
//       next: None,
//       val
//     }
//   }
// }
impl Solution {
    pub fn remove_elements(head: Option<Box<ListNode>>, val: i32) -> Option<Box<ListNode>> {
        let mut head = head;
        // 判断head是否为要删除的
        while let Some(node) = head.as_ref() {
            if node.val == val {
                head = head.unwrap().next
            } else {
                break;
            }
        }

        let mut curr = &mut head;

        while let Some(node) = curr {
            while let Some(node_next) = node.next.as_mut() {
                if node_next.val == val {
                    node.next = node_next.next.take();
                } else {
                    break;
                }
            }
            curr = &mut node.next;
        }

        head
        
    }
}

以上代码中,遇到的第一个疑问:

let mut head = head;

这里是rust的一个特性,变量遮蔽,将遮蔽之前的拥有所有权的head,好处是现在的head变量是可变的;

while let Some(node) = head.as_ref() {
    if node.val == val {
        head = head.unwrap().next
    } else {
        break;
    }
}

这里node是一个head的引用,为什么还能head = head.unwrap().next,从生命周期角度来说,由于NLL,会找到最后一次使用node的位置,来标记它结束的位置,因此在node.val == val这个表达式这里结束了,和head这里修改和之前的引用不冲突。

let mut curr = &mut head;这里的含义非常丰富。

  1. curr是一个可变的变量
  2. curr的类型是一个&Option<Box<ListNode>>
  3. curr所借用的head是可变的,改变它的内容的。

这里先默念curr是一个可变引用,

 while let Some(node) = curr {
    while let Some(node_next) = node.next.as_mut() {
        if node_next.val == val {
            node.next = node_next.next.take();
        } else {
            break;
        }
    }
    curr = &mut node.next;
}

重点来了

while let Some(node) = curr这个表达了什么?

node是Some<Box>中Box的一个可变再借用。

这里隐式的发生了再借用。在使用再借用的变量时,不能使用被再借用的变量,否则会报错。先记住这个关键点。

while let Some(node_next) = node.next.as_mut()什么!!!又是对node再一次可变借用?到底是什么👻?

这里其实是对nodenext字段进行了一个可变借用,这个规则是允许的。

等等。还有个问题。那就是next_node一份数据同时被nodenext字段指向,以及next_node可变引用指向,这又问题了!next字段的是一个站上指向**Box<ListNode>**节点的指针,Box又指向了实际的值。

不是node的可变引用会导致他后边所有的节点的可变引用都被占有吗?

这里其实就是隐式的再借用,还是不能在再借用生命周期结束之前,对被借用的使用。

node.next = node_next.next.take(); 这不是在同一行么,不是冲突了吗?

其实这里右值先于左值结束,

curr = &mut node.next;这里生命周期不冲突了,curr在可变借用存在下,修嘎curr

这里先要明确curr是一个可变量。

  1. node 仍然存在,仍然借用 *curr 的旧值(head)
  2. curr 被重新赋值,指向新的位置(node.next)
  3. 这不是两个借用同时存在,而是 curr 改变了指向
posted @ 2026-01-20 02:38  咕咚!  阅读(47)  评论(0)    收藏  举报