如何解决[E0382]: 在for循环中使用已移动的值?

4

请帮我解决以下错误:

error[E0382]: use of moved value: `nd3`
  --> src/main.rs:21:21
   |
19 |     Node::Y { nd: nd3, max: max } => {
   |                   --- move occurs because `nd3` has type `std::boxed::Box<Node>`, which does not implement the `Copy` trait
20 |       for m in 0..max - 1 {
21 |         match recur(nd3) {
   |                     ^^^ value moved here, in previous iteration of loop

以下是代码。请不要在意代码看起来毫无意义,因为我对它进行了简化:
enum Node {
  X { x: usize },
  Y { nd: Box<Node>, max: usize },
  Z { Nd: Vec<Box<Node>> },
}

fn recur(nd: Box<Node>) -> Result<usize, ()> {
  match *nd {
    /// ...
    Node::Y { nd: nd3, max: max } => {
      for m in 0..max - 1 {
        match recur(nd3) {
          Ok(y) => return Ok(y),
          _ => {}
        }
      }
      return Ok(123);
    }
    _ => {}
  }
  return Ok(0);
}

1个回答

3
如果您拥有一个值(nd),并在其上进行迭代,然后再次对其进行迭代,由于它已被移动到循环的前一次迭代中,因此会出现错误。
一种解决方法是为Node派生Clone特征。 Clone是一个常见的特征,用于显式复制一个对象:
#[derive(Clone)]
enum Node {
  X { x: usize },
  Y { nd: Box<Node>, max: usize },
  Z { Nd: Vec<Box<Node>> },
}

现在你可以通过递归调用函数再次克隆nd3:
Node::Y { nd: nd3, max: max } => {
  for m in 0..max - 1 {
    match recur(nd3.clone()) {
      Ok(y) => return Ok(y),
      _ => {}
    }
  }
  return Ok(123);
}

现在,你没有将所拥有的值传递给下一次循环。相反,你传递了一个完全的复制品。另一种解决方案是借用这个值。但对于较小的对象而言克隆更加容易。


7
对于Rust初学者的建议:克隆,毫不犹豫地克隆。先熟悉这门语言,然后深呼吸,开始学习借用。学习所有权/借用已经足够困难了,你不想同时遇到其他问题而跌跌撞撞。 - Matthieu M.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接