面试题答案
一键面试实现自定义迭代器要点
- 生命周期管理:
- 迭代器中的引用必须有明确且合理的生命周期。如果迭代器返回集合元素的引用,这些引用的生命周期必须至少与迭代器本身一样长。这通常通过在迭代器结构体和其方法上正确标注生命周期参数来实现。
- 例如,如果迭代器遍历一个包含引用的集合,要确保这些引用的生命周期不会过早结束,以免造成悬垂引用。
- 性能优化:
- 尽量避免不必要的内存分配和复制。如果集合元素是大对象,返回引用而不是值可以显著提高性能。
- 实现
Iterator
特征的方法时,确保方法的时间复杂度是合理的。例如,next
方法应该在常数时间内完成(如果可能的话),避免在每次调用next
时进行复杂的计算。
代码实现示例
// 自定义集合类型
struct MyCollection<T> {
data: Vec<T>,
}
impl<T> MyCollection<T> {
fn new() -> Self {
MyCollection { data: Vec::new() }
}
fn push(&mut self, item: T) {
self.data.push(item);
}
}
// 自定义迭代器结构体
struct MyIterator<'a, T> {
data: &'a [T],
index: usize,
}
impl<'a, T> Iterator for MyIterator<'a, T> {
type Item = &'a T;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.data.len() {
let result = Some(&self.data[self.index]);
self.index += 1;
result
} else {
None
}
}
}
impl<'a, T> IntoIterator for &'a MyCollection<T> {
type Item = &'a T;
type IntoIter = MyIterator<'a, T>;
fn into_iter(self) -> Self::IntoIter {
MyIterator {
data: &self.data,
index: 0,
}
}
}
fn main() {
let mut collection = MyCollection::new();
collection.push(1);
collection.push(2);
collection.push(3);
for item in &collection {
println!("{}", item);
}
}
在上述代码中:
- 首先定义了一个自定义集合类型
MyCollection
,它内部使用Vec<T>
来存储数据。 - 然后定义了自定义迭代器
MyIterator
,它持有集合数据的引用&[T]
和当前遍历的索引index
。 - 为
MyIterator
实现了Iterator
特征,其中next
方法返回下一个元素的引用,直到遍历完所有元素返回None
。 - 还为
&MyCollection<T>
实现了IntoIterator
特征,这样就可以方便地使用for
循环来遍历集合。