не может выйти из заимствованного контента для Vec, но не для u64

Следующий код выдает ошибку:

struct Foo {
    a: Vec<u64>,
}

impl Foo {
    fn change_a(&mut self, new_a: Vec<u64>) {
        self.a = *choose(&self.a, &new_a);
    }
}

fn choose<'a>(x: &'a Vec<u64>, y: &'a Vec<u64>) -> &'a Vec<u64> {
    return if x > y { x } else { y };
}

fn main() {
    let mut foo = Foo { a: vec![1] };
    foo.change_a(vec![3]);
    println!("{:?}", foo.a);
}

Ошибка:

error[E0507]: cannot move out of borrowed content
 --> src/main.rs:7:18
  |
7 |         self.a = *choose(&self.a, &new_a);
  |                  ^^^^^^^^^^^^^^^^^^^^^^^^ cannot move out of borrowed content

Этот код работает нормально, если я заменю Vec<u64> только на u64.

В чем разница?


person mavix    schedule 27.03.2017    source источник
comment
Может быть, что-то связано с тем, что время жизни векторного элемента отделено от самого вектора? то есть каждый элемент вектора должен иметь время жизни не менее self.a.   -  person Nick Sweeting    schedule 27.03.2017


Ответы (2)


Примитивный тип u64 реализует Copy. Это означает, что u64 имеет «семантику копирования»: если компилятор обнаружит, что мы пытаемся завладеть T: Copy, но значение, из которого перемещается, все еще используется, T будет скопировано.

Vec это не Copy, а Clone, то есть мы можем сделать

self.a = choose(& self.a, & new_a).clone();

Чтобы решить эту проблему.

Вот еще один пример семантики копирования на вашем примере

person Emilgardis    schedule 27.03.2017

Разница в том, что u64 реализует Copy, а Vec<u64> реализует нет. Когда вы пытаетесь переместить значение типа, реализующего Copy, но перемещаемое значение нельзя переместить, компилятор на самом деле не переместит его, а вместо этого скопирует, поэтому версия с u64 компилируется нормально.

person Francis Gagné    schedule 27.03.2017