rust - 变量所有权在迭代之间如何工作?

标签 rust

我试图学习使用rust ,并想到将链接列表作为实践问题来理解所有权/借用概念,并且遇到了困难。pushLinkedList方法应按以下方式工作:

t = 0 | root: None | push 5
t = 1 | root: { value: 5, next: None } | push 6
t = 2 | root: { value: 5, next: { value: 6, None } } |
这是尝试执行相同操作的代码:
#[derive(Debug, Clone)]
struct Node {
  value: u32,
  next: Option<Box<Node>>,
}

impl Node {
  fn new(value: u32) -> Node {
    Node { value, next: None }
  }
}

#[derive(Debug, Clone)]
struct LinkedList {
  root: Option<Box<Node>>,
}

impl LinkedList {
  fn new(node: Option<Box<Node>>) -> LinkedList {
    LinkedList { root: node }
  }

  fn push(self, node: Option<Box<Node>>) {
    let maybe_node = self.root;

    loop {
      match maybe_node {
        Some(tail_node) => {  // use of moved value. std::boxed::Box<Node> doesn't implement copy trait. --- (1)
          if tail_node.next.is_none() {
            tail_node.next = node; // tail_node is not mutable. --- (2)
            break;
          };
        }
        _ => (),
      }
    }
  }
}

fn main() {
  let mut node = Node::new(0);
  let linked_list = LinkedList::new(Some(Box::new(node)));

  for number in 1..5 {
    node = Node::new(number);
    linked_list.push(Some(Box::new(node))); // move occurs. Value moved here in a previous iteration --- (3)
  }
  println!("{:?}", linked_list);
}
我不明白“移动发生”错误(1、3),我不清楚值移到哪里了?似乎是迭代导致所有权发生变化,但我看不出怎么做。
另外,错误(2)我的实现是最好的方法吗?

最佳答案

在Rust中,有两种方式处理所有权,即移动语义或借用语义。这是一些了解它的规则。
第一条规则是每个数据块只能同时拥有一个所有者。如果将某个变量分配给其他变量,则可以有效地移动数据,并且数据将由新所有者拥有。
第二条规则是,如果您拥有某些数据,该数据归某人所有,但您想读取它,则可以借用它。借阅本质上是获取对数据的引用,该数据由其他人拥有。
现在回到您的问题。在函数声明中,您已将第一个参数声明为self


fn push(self, node: Option<Box<Node>>) {
   let maybe_node = self.root;

   loop {
     match maybe_node {
       Some(tail_node) => {  // use of moved value. std::boxed::Box<Node> doesn't implement copy trait. --- (1)
         if tail_node.next.is_none() {
           tail_node.next = node; // tail_node is not mutable. --- (2)
           break;
         };
       }
       _ => (),
     }
   }
 }
从本质上讲,这意味着在调用函数时,您将获取自我的所有权,因此使任何先前的所有者无效。循环中发生的事情是,在第一次迭代中,该值被移入了函数,并且不再由linked_list拥有。在第二次迭代中,您再次尝试访问数据,但是它不再有效,因为它已被移到函数中。
为了规避您的问题,您将需要声明您的函数,如下所示:
 fn push(&mut self, node: Option<Box<Node>>) {
    let maybe_node = self.root;

    loop {
      match maybe_node {
        Some(tail_node) => {  // use of moved value. std::boxed::Box<Node> doesn't implement copy trait. --- (1)
          if tail_node.next.is_none() {
            tail_node.next = node; // tail_node is not mutable. --- (2)
            break;
          };
        }
        _ => (),
      }
    }
  }
在上面的声明中,您说的是您正在借用self,并且希望对其进行更改(这就是我们拥有&mut而不是&的原因)。
有关更多详细信息,请引用chapter about ownership in Rust book

关于rust - 变量所有权在迭代之间如何工作?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65493710/

相关文章:

generics - 如何定义对可以进行按位运算的整数通用的 Rust 函数?

rust - 生命周期必须对静态生命周期有效

rust - HashMap 的 split_at_mut 等效吗?

rust - 引用内部闭包的迭代器的智能构造函数

rust - rust 迹所有权-由于存在 “behind a shared reference”而无法移动

rust - "overflow evaluating the requirement"尝试延迟关联类型时

rust - 如何忽略 .gitignore 中的 Rust 可执行文件?

rust - 为什么在使用非文字模式时无法访问此匹配模式?

rust - 如何将切片的每个元素作为单独的参数传递给可变参数 C 函数?

random - 无法创建向量并将其打乱