Почему перебор коллекции с помощью цикла for считается в Rust ходом?

У меня есть программа на Rust ниже.

fn main() {
    let v = vec![100, 32, 57];
    for i in v {
        println!("{}", i);
    }

    println!("{:?}", v);
}

Когда я запускаю его, я получаю:

error[E0382]: borrow of moved value: `v`
 --> src\main.rs:7:22
  |
2 |     let v = vec![100, 32, 57];
  |         - move occurs because `v` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait
3 |     for i in v {
  |              -
  |              |
  |              value moved here
  |              help: consider borrowing to avoid moving into the for loop: `&v`
...
7 |     println!("{:?}", v);
  |                      ^ value borrowed here after move

В сообщении об ошибке указано, что в for i in v произошло перемещение. Но я просто использую ту же переменную v, определенную let v = vec![100, 32, 57]. Это не что-то вроде let v2 = v; for i in v2 ..., который переместил значение с v на v2. Может ли кто-нибудь помочь немного объяснить?


person Just a learner    schedule 01.12.2019    source источник


Ответы (1)


Как https://doc.rust-lang.org/reference/expressions/loop-expr.html#iterator-loops говорит:

Выражение for - это синтаксическая конструкция для перебора элементов, предоставляемая реализацией std::iter::IntoIterator.

Vec реализует IntoIterator, что позволяет владеть элементами экземпляра Vec, потребляя его:

Создает потребляющий итератор, то есть тот, который перемещает каждое значение из вектора (от начала до конца). Вектор не может быть использован после этого вызова.

(Как отмечается в сообщении об ошибке, способ исправить это - перебрать &v вместо v, заимствуя его элементы вместо того, чтобы владеть ими. Вы можете выполнить цикл for &i in &v, чтобы сохранить тип i.)

На высоком уровне вам может показаться ненужным владение элементами v, поскольку они могут быть скопированы, но нет специальной реализации, позволяющей использовать эту информацию здесь. IntoIterator.into_iter() принимает self, что означает, что цикл for всегда использует значение, по которому выполняется итерация.

person Ry-♦    schedule 01.12.2019