Ответ 1
Как вы сказали, for
работ, взяв вещь, которую вы попросили IntoIterator::into_iter
, и передав ее через IntoIterator::into_iter
для получения фактического значения итератора. Также, как вы сказали, into_iter
получает тему по значению.
Таким образом, при попытке перебрать Vector
непосредственно, это означает, что вы пройдете весь вектор, по значению, в свою IntoIterator
реализации, тем самым потребляя вектор в этом процессе. Вот почему вы не можете выполнить итерацию по вектору напрямую дважды: итерацию по нему в первый раз, когда он потребляется, после чего он больше не существует.
Однако срезы отличаются: срез является неизменным, заимствованным указателем на свои данные; неизменные, заимствованные указатели могут быть скопированы свободно. Это означает, что IntoIterator
для неизменяемых фрагментов просто заимствует данные и не использует их (не так, как мог бы). Или, чтобы взглянуть на это иначе, его реализация IntoIterator
просто берет копию среза, тогда как вы не можете скопировать Vec
.
Следует отметить, что вы можете перебирать Vec
не потребляя его, перебирая заем. Если вы проверите документацию для Vec
, вы заметите, что в ней перечислены реализации IntoIterator
для Vec<T>
, &Vec<T>
и &mut Vec<T>
.
let mut a: Vec<i32> = vec![1, 2, 3];
for i in &a { // iterate immutably
let i: &i32 = i; // elements are immutable pointers
println!("{}", i);
}
for i in &mut a { // iterate mutably
let i: &mut i32 = i;// elements are mutable pointers
*i *= 2;
}
for i in a { // iterate by-value
let i: i32 = i; // elements are values
println!("{}", i);
}
// 'a' no longer exists; it was consumed by the previous loop.