首页 文章

尝试转让所有权时,无法摆脱借来的内容

提问于
浏览
12

我正在编写一个链表来包围Rust的生命周期,所有权和引用 . 我有以下代码:

pub struct LinkedList {
    head: Option<Box<LinkedListNode>>,
}

pub struct LinkedListNode {
    next: Option<Box<LinkedListNode>>,
}

impl LinkedList {
    pub fn new() -> LinkedList {
        LinkedList { head: None }
    }

    pub fn prepend_value(&mut self) {
        let mut new_node = LinkedListNode { next: None };

        match self.head {
            Some(ref head) => new_node.next = Some(*head),
            None => new_node.next = None,
        };

        self.head = Some(Box::new(new_node));
    }
}

fn main() {}

但是我收到以下编译错误:

error[E0507]: cannot move out of borrowed content
  --> src/main.rs:18:52
   |
18 |             Some(ref head) => new_node.next = Some(*head),
   |                                                    ^^^^^ cannot move out of borrowed content

我认为 head 节点当前必须由 self 拥有,这是链表 . 当我将其分配给 new_node.next 时,可能会发生所有权变更 .

如果可能的话,我宁愿不克隆 Value ,因为这看起来很浪费 . 我不想在函数期间“借用”它 . 我真的想转让它的所有权 .

我怎么做?

我已经看过error: cannot move out of borrowed content on &mut selfCannot move out of borrowed content .

我尝试在其中一个问题的接受答案中建议删除匹配臂,并在创建新 LinkedListNode 时定义 next ,但是我收到相同的错误消息 .

我已经成功添加了一个 append 方法,它将 LinkedListNode 添加到列表的末尾 .

1 回答

  • 22

    尝试转移所有权时,无法摆脱借来的内容

    在高层次上,这对Rust来说是违规的 . 你不能转让借来的东西的所有权,因为你不拥有它 . 你不应该借我的车( &Car ),然后把它交给你在街上看到的第一个人!即使我借给你我的车并允许你对它进行更改( &mut Car ),这仍然是正确的 .

    您根本无法移动 head &self 因为您无法改变该值 .

    你不能将 head 移出 &mut self ,因为这会使 LinkedList 结构处于不一致状态 - 其中一个字段将具有未定义的值 . 这是Rust安全保障的核心指标 .

    通常,您需要遵循How can I swap in a new value for a field in a mutable reference to a structure?中的内容来替换现有值 .

    在这种情况下,您可以使用Option::take . 这将使变量保持原样,将其原地更改为 None 并返回先前的值 . 然后,您可以使用该值来构建列表的新头:

    pub fn prepend_value(&mut self) {
        let head = self.head.take();
        self.head = Some(Box::new(LinkedListNode { next: head }));
    }
    

    更通用的解决方案是获取结构的所有权而不是借用它 . 这允许你做任何你想做的事情 . 请注意,我们采用 self by-value,而不是by-reference:

    pub fn prepend_value(mut self) -> LinkedList {
        self.head = Some(Box::new(LinkedListNode { next: self.head }));
        self
    }
    

相关问题