Почему `ref mut` для привязки цикла for не совпадает с` & mut` для зацикливаемой переменной? - PullRequest
0 голосов
/ 05 декабря 2018

В Rust по Примеру написано:

ref заем в левой части присвоения эквивалентен & заеме в правой части.

Я думал, что эти два for цикла будут эквивалентны:

Компилируется успешно:

let mut v2 = vec![1, 2, 3];
for i in &mut v2 {
    *i = *i + 1;
}
println!("{:?}", v2);

Не компилируется:

let mut v1 = vec![1, 2, 3];
for ref mut i in v1 {
    *i = *i + 1;
}
println!("{:?}", v1);

Кажется, v перемещено:

error[E0382]: use of moved value: `v1`
 --> src/main.rs:6:22
  |
3 |     for ref mut i in v1 {
  |                      -- value moved here
...
6 |     println!("{:?}", v1);
  |                      ^^ value used here after move
  |
  = note: move occurs because `v1` has type `std::vec::Vec<i32>`, which does not implement the `Copy` trait

1 Ответ

0 голосов
/ 05 декабря 2018

То, что вы цитируете из книги, является правилом для обычных заданий, таких как let.Например:

let x = &42;
let ref x = 42;

Но привязка имени в цикле for немного отличается:

  • Зацикливаемое значение преобразуется в итератор (<v1 as IntoIterator>::into_iter()) Позволяет вызвать результат этого it.
  • Затем it.next() вызывается повторно:
    • Если он возвращает Some(_), то значение этого связано с вашей переменной.Как будто вы написали let Some(ref mut i) = it.next() или let Some(mut i) = it.next().Вот где ref имеет значение.
    • Если он возвращает None, цикл заканчивается.

Так что в случае цикла for,ref и & не эквивалентны.

Когда вы используете & в правой части цикла, это не меняет привязку переменной напрямую;Вы просто меняете тип объекта с повторением.Затем все сводится к реализации IntoIterator для Vec<_> против того, что для &Vec<_>.

  • Если вы итерируете Vec<T>, он становится владельцем вектора, и итерация возвращаетСами ценности.Таким образом, for i in v1 использует вектор, а i имеет тип содержащихся значений T.
  • Если вы итерируете &Vec<T>, он заимствует вектор и указатели возврата итерации к содержащимся значениям &T, поэтому в for i in &v1 тип i фактически является указателем на значения.Тот же эффект можно получить с помощью for i in v1.iter().
  • . Если вы итерируете &mut Vec<T>, то же самое, что и предыдущий, но изменяемый, поэтому итерация возвращает значения типа &mut T.
.

Вывод состоит в том, что использование ref в цикле for, вероятно, не очень полезно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...