error: use of moved value - should I use “&” or “m

2019-09-01 03:55发布

My code:

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`

How can I fix them? Should I add & to the parameters of 'fn2andfn3? Ormut`? I can't understand the idea of how to fix these kind of errors.

标签: rust
1条回答
神经病院院长
2楼-- · 2019-09-01 03:58

These errors come from the most important concept in Rust - ownership. You should read the official book, especially the chapter on ownership - this would help you understand "how tho fix this kind of errors".

In short, specifically in your code, the problem is that String is a non-copyable type, that is, String values are not copied when passed to functions or assigned to local variables, they are moved. This means that wherever they were before, they are not accessible from there anymore.

Let's look at your function:

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 {
  //....   
}

All types here are not automatically copyable (they don't implement Copy trait). String is not copyable because it is a heap-allocated string and copying would need a fresh allocation (an expensive operation which better be not implicit), MyEnum1 is not copyable because it does not implement Copy (with #[deriving(Copy, Clone)], for example; and it is unclear if it can be made copyable because you didn't provide its variants), and Struct1 is not copyable because it contains non-copyable types.

In fn1 you invoke fn2, passing it field1 and getting a String back. Then you immediately passes this String to fn3. Because String is not copyable, whatever is stored in let1 is moved into the called function, making let1 inaccessible. This is what "use of moved value" error is about. (The code you provided can't cause "use of moved value: a.field1" error, so it probably came from the parts you omitted, but the basic idea is absolutely the same)

There are several ways to fix these errors, but the most natural and common one is indeed to use borrowed references. In general if you only want to read some non-copyable value in a function you should pass it there by reference:

fn use_myenum(e: &MyEnum1)

For strings and arrays, however, the better way would be to pass slices:

fn use_str(s: &str) { ... }

let s: String = ...;
use_str(&s);  // here &String is automatically converted to &str

You can find more on slices in the book, here.

查看更多
登录 后发表回答