Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/rust/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Rust 变量的所有权如何在迭代之间工作?_Rust - Fatal编程技术网

Rust 变量的所有权如何在迭代之间工作?

Rust 变量的所有权如何在迭代之间工作?,rust,Rust,我正在努力学习rust,并考虑将实施链表作为一个实践问题来理解所有权/借用概念,我现在很难理解 LinkedList的push方法应如下所示: 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

我正在努力学习rust,并考虑将实施链表作为一个实践问题来理解所有权/借用概念,我现在很难理解

LinkedList
push
方法应如下所示:

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);
}
#[派生(调试、克隆)]
结构节点{
值:u32,
下一步:选择,
}
impl节点{
fn新(值:u32)->节点{
节点{值,下一个:无}
}
}
#[派生(调试、克隆)]
结构链接列表{
根:选项,
}
impl链接列表{
fn新建(节点:选项)->LinkedList{
LinkedList{root:node}
}
fn推送(自身,节点:选项){
让node=self.root;
环路{
匹配节点{
Some(tail_node)=>{//使用移动值。std::boxed::Box未实现复制特性。--(1)
如果tail\u node.next.is\u none(){
tail\u node.next=node;//tail\u节点不可变。--(2)
打破
};
}
_ => (),
}
}
}
}
fn main(){
让mut node=node::new(0);
让linked_list=LinkedList::new(Some(Box::new(node));
对于1..5中的数字{
节点=节点::新(编号);
linked_list.push(Some(Box::new(node));//发生移动。值在上一次迭代中移动到此处---(3)
}
println!(“{:?}”,链表);
}
我不理解“移动发生”错误(1,3)。我不清楚值移动到了哪里?迭代似乎正在导致所有权发生变化,但我看不出是如何变化的


此外,错误(2)是我实现的最佳方式?

在Rust中,有两种方式是处理所有权,即移动语义或借用语义。这里有一些关于理解它的规则

第一条规则是,每条数据在同一时间只能有一个所有者。如果将某个变量分配给另一个变量,则可以有效地移动数据,数据将归新所有者所有

第二条规则是,如果你有一些属于某人的数据,但你想读它,那么你可以借用它。借用本质上是获取对数据的引用,这些数据由其他人拥有

现在回到你的问题上来。在函数声明中,您已将第一个参数声明为
self


fn推送(自身,节点:选项){
让node=self.root;
环路{
匹配节点{
Some(tail_node)=>{//使用移动值。std::boxed::Box未实现复制特性。--(1)
如果tail\u node.next.is\u none(){
tail\u node.next=node;//tail\u节点不可变。--(2)
打破
};
}
_ => (),
}
}
}
这本质上意味着,当你调用你的函数时,你拥有了self的所有权,因此你使任何以前的所有者无效。循环中发生的情况是,在第一次迭代中,该值被移动到函数中,不再属于
链接列表
。在第二次迭代中,您再次尝试访问数据,但它不再有效,因为它已被移动到函数中

为了避免您的问题,您需要声明您的函数,如下所示:

fn推送(&mut self,节点:选项){
让node=self.root;
环路{
匹配节点{
Some(tail_node)=>{//使用移动值。std::boxed::Box未实现复制特性。--(1)
如果tail\u node.next.is\u none(){
tail\u node.next=node;//tail\u节点不可变。--(2)
打破
};
}
_ => (),
}
}
}
在上面的声明中,您表示您正在借用
self
,并且希望对其进行更改(这就是为什么我们有
&mut
,而不仅仅是
&


有关更多详细信息,请参阅。

您的
推送
方法消耗
链接列表
,因为它按值获取
自我
,而不是
&mut self
“我正试图学习生锈并考虑将实现链接列表作为一个实践问题”您成为经典错误之一的受害者。最著名的是从不创建自引用数据结构,但这一点鲜为人知:。感谢您提供详细的答案。“循环中发生的事情是,在第一次迭代中,值被移动到函数中,不再属于链接列表”好的,我很难理解这一点,但这意味着如果我调用
。按一下
,实例
链接列表
“移动”到函数中?所以,如果我只是阅读的话,
&self
就足够了?而不是变异什么?我理解这种混乱。从我的角度看,你似乎已经理解了一切。如果只有
&
,则只能读取,这也适用于结构的所有内部字段,因此,如果将
&
转换为结构,则无法更改结构或结构中的任何数据。由于您有
tail\u node.next=node
分配,因此您需要更改选项的内容
&mut