Moving a vector out of a struct (no cloning/copying)

fn main() {
    struct Foo {
        c: Vec<u32>,
    }
    let f = Foo {
        c: Vec::new(),
    };
    let d = f.c; // this works!
    //println!("f.c {:?}", f.c); // f.c is moved
    println!("d {:?}", d);
    let vf = vec![Foo {
        c: vec![0, 1, 2],
    }];
    let e = vf[0].c; // isn't this the same??? works if &vf[0].c
    println!("vf[0].c {:?}", vf[0].c);
    println!("e {:?}", e);
}

(Playground)

Errors:

   Compiling playground v0.0.1 (/playground)
error[E0507]: cannot move out of index of `Vec<Foo>`
  --> src/main.rs:14:13
   |
14 |     let e = vf[0].c; // isn't this the same??? works if &vf[0].c
   |             ^^^^^^^ move occurs because value has type `Vec<u32>`, which does not implement the `Copy` trait
   |
help: consider borrowing here
   |
14 |     let e = &vf[0].c; // isn't this the same??? works if &vf[0].c
   |             +
help: consider cloning the value if the performance cost is acceptable
   |
14 |     let e = vf[0].c.clone(); // isn't this the same??? works if &vf[0].c
   |                    ++++++++

For more information about this error, try `rustc --explain E0507`.
error: could not compile `playground` (bin "playground") due to 1 previous error

this isn't the same, the first partial move is because you have an owned Foo, but vf[0] is behind a reference, the indexing operator (i.e. square brackets) is desugared to the std::ops::Index trait, which has this signature:

    fn index(&self, index: Idx) -> &Self::Output;

if you want to move out the Vec from the struct, and you have a mut reference, you can use std::mem::take(), which moves the Vec out and replaces it with an empty Vec (via the Default trait).

2 Likes

To complete the comparison, this doesn't work either.

let d = (*&f).c;

Thanks, mem::take() worked like a charm! Now, I can go wotk on the rest of what you wrote, to understand better what array indexing actually does :slight_smile:

Much appreciated!
K

@nerditation Love your handle, btw!

Indeed it doesn’t! Good comparison.

So much to learn … Thanks!