错误:使用移动值 - 我应该使用“&”或“mut”或其他什么?

时间:2015-06-22 05:35:10

标签: rust

我的代码:

enum MyEnum1 {
  //....
}

struct Struct1 { 
  field1: MyEnum1,
  field2: String
}

fn fn1(a: Struct1, b: String, c: String) -> String {
  let let1 = fn2(a.field1);
  let let2 = fn3(let1, b, c);
  format!("{} something 123 {}", let1, let2)
}


fn fn2(a: MyEnum1) -> String {
  //....   
}

fn fn3(a: MyEnum1, b: Struct1) -> String {
  //....   
}


error: use of moved value: `a.field1`
error: use of moved value: `let1`

我该如何解决?我应该将&添加到'fn2 and fn3 ? Or mut`的参数中吗?我无法理解如何解决这些错误。

1 个答案:

答案 0 :(得分:3)

这些错误来自Rust中最重要的概念 - 所有权。您应该阅读the official book,尤其是关于ownership的章节 - 这有助于您理解“如何解决此类错误”。

简而言之,特别是在您的代码中,问题是String是一个不可复制的类型,即String值在传递给函数或分配给局部变量时不会被复制,它们是移动。这意味着无论他们以前在哪里,都无法从那里访问它们。

让我们来看看你的功能:

enum MyEnum1 {
  //....
}

struct Struct1 { 
  field1: MyEnum1,
  field2: String
}

fn fn1(a: Struct1, b: String, c: String) -> String {
  let let1 = fn2(a.field1);
  let let2 = fn3(let1, b, c);
  format!("{} something 123 {}", let1, let2)
}

fn fn2(a: MyEnum1) -> String {
  //....   
}

此处的所有类型都不能自动复制(它们不实现Copy特征)。 String不可复制,因为它是一个堆分配的字符串,复制需要一个新的分配(一个昂贵的操作,最好不要隐式),MyEnum1不可复制,因为它没有实现{{1 (例如,Copy;并且不清楚它是否可以复制,因为您没有提供其变体),#[deriving(Copy, Clone)]不可复制,因为它包含不可复制的类型。

Struct1中,您调用fn1,传递fn2并获得field1。然后,您立即将此String传递给String。由于fn3不可复制,因此String中存储的内容已移动到被调用函数中,导致let1无法访问。这就是“使用移动值”错误的原因。 (您提供的代码不会导致“使用移动值:let1”错误,因此它可能来自您省略的部分,但基本思想绝对相同)

有几种方法可以解决这些错误,但最自然和最常见的方法确实是使用借用的引用。通常,如果您只想读取函数中的某些不可复制值,则应通过引用将其传递给它:

a.field1

对于字符串和数组,更好的方法是传递切片:

fn use_myenum(e: &MyEnum1)

您可以在书中找到有关切片的更多信息,here