为什么Rust中无法多次遍历同一个vec.iter()生成的迭代器?
核心原因
这个报错和iter()返回内部元素引用没有任何关系,问题出在for循环的实现机制和迭代器本身的语义上:
- Rust的
for循环是语法糖,执行时会隐式对in后面的对象调用into_iter(),而IntoIterator对迭代器类型的实现是按值接收self,直接返回迭代器本身,也就是说第一次写for z in iterator的时候,iterator变量的所有权就已经被转移到循环内部了,循环结束后这个变量就被释放失效,第二次循环自然无法使用已经被移动的值。 - 你通过
x.iter()或者(&x).into_iter()拿到的std::slice::Iter<'_, i32>本质是一次性遍历游标,内部维护了当前遍历位置的指针,遍历过程中会不断修改这个指针的状态,它本身就不是设计用来支持重复遍历的对象。哪怕它产出的元素是不获取所有权的共享引用,也不代表迭代器自身可以被反复使用。
多次遍历的正确实现
如果需要对同一个Vec执行多次遍历,不要提前把迭代器实例存到变量里反复用,每次遍历前从源集合创建全新的迭代器即可:
let x = vec![1,2,3]; // 第一次遍历,创建第一个Iter实例 for z in x.iter() {} // 第二次遍历,创建第二个全新的Iter实例,两个迭代器的遍历状态互不干扰 for z in x.iter() {}
如果不想反复写x.iter(),可以存集合的共享引用代替存迭代器:
let x = vec![1,2,3]; // 存的是Vec的共享引用,不是迭代器,共享引用实现了Copy trait let iter_handle = &x; // 每次循环都会自动复制引用、生成新的迭代器,不会拿走原变量所有权 for z in iter_handle {} for z in iter_handle {}
常见误区:不要混淆「迭代器产出元素的所有权规则」和「迭代器自身的所有权规则」。迭代器产出引用只代表遍历过程中不会修改/拿走集合内元素的所有权,和迭代器本身能不能被重复遍历、会不会被消耗完全是两个独立的特性。标准库提供的基础迭代器(
Iter/IterMut/IntoIter)全都是一次性消耗品,遍历完成后就会被释放,不存在复用同一个迭代器实例多次遍历的用法。
内容的提问来源于stack exchange,提问作者bluseking Zhuo
相关产品推荐
相关产品推荐

