Rust заимствует странное поведение
Как и код ржавчины ниже: whileцикл компилируется и работает нормально, но for iterверсия не компилируется из-за ошибки:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:22:9
|
20 | for i in v.iter() {
| --------
| |
| immutable borrow occurs here
| immutable borrow later used here
21 | println!("v[i]: {}", i);
22 | v.push(20);
| ^^^^^^^^^^ mutable borrow occurs here
error: aborting due to previous error
Но, как я понял, whileцикл также имеет тот же сценарий, lenа getтакже имеет неизменное заимствование, почему он не конфликтует с pushкак заимствовать изменчиво? Пожалуйста, посоветуйте, чего мне здесь не хватает, большое спасибо за просветление!
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
let mut i = 0;
while i < v.len() && i < 10 {
v.push(20);
println!("v[i]: {:?}", v.get(i));
i += 1;
}
// for i in v.iter() {
// println!("v[i]: {}", i);
// v.push(20);
// }
}
Ответы
forВерсия кода примерно эквивалентно следующему:
fn main() {
let mut v = Vec::new();
v.push(1);
v.push(2);
v.push(3);
v.push(4);
let mut it = v.iter();
while let Some(i) = it.next() {
println!("v[i]: {}", i);
v.push(20);
}
}
Игровая площадка
Если вы попытаетесь скомпилировать это, вы получите ошибку, которая может иметь немного больше смысла:
error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable
--> src/main.rs:11:9
|
8 | let mut it = v.iter();
| - immutable borrow occurs here
9 | while let Some(i) = it.next() {
| -- immutable borrow later used here
10 | println!("v[i]: {}", i);
11 | v.push(20);
| ^^^^^^^^^^ mutable borrow occurs here
Итератор vнеизменно заимствует заимствования на протяжении всего цикла, поэтому вы не можете принимать какие-либо изменяемые заимствования внутри цикла.
Конечно, даже если бы вы могли это сделать, у вас получился бы бесконечный цикл, потому что вы продолжали добавлять еще один элемент.
Проще говоря, когда вы звоните .iter(), вы создаете новые объекты (итератор), который заимствует свой вектор (непреложно), и дает элемент один за другим, что означает , что вы на самом деле брать vв целом время цикла . С другой стороны, когда вы обращаетесь к нему через, .get(i)вы напрямую заимствуете один элемент за раз из вектора, и поэтому он освобождается от ограничений заимствования, когда вы push.
Причина такого ограничения очень проста: представьте, что ваш реальный forцикл скомпилирован, он будет работать вечно (и чтобы предотвратить это в whileцикле, вам пришлось добавить искусственное условие i<10!), Тогда как это явно не намеченная цель (или если было бы очевидно, что вы бы сделали это иначе, например, с помощью оператора while letили loop), и Rust пытается предотвратить вас «выстрелить себе в ногу», потому что вы на самом деле не знаете, как делать то, что хотите, и пытаетесь сделать не то путь.
Чтобы делать то, что вы хотели, вы могли:
for i in 0..v.len() {
v.push(20)
}
потому что v.len()вызов не заимствует vвремя всего forцикла, а только в начале.