Rust迭代器元素组合结构体开发:元素引用存储问题求助
问题:Rust中如何正确存储迭代器元素的引用以实现组合结构体?
我Rust开发经验较少,可能存在概念误解。现尝试开发一个可遍历迭代器元素组合的结构体,需要在结构体中存储迭代器元素的引用,但未能实现。以下是我的代码:
pub struct Combination<'a, T: Iterator> { _obj_items_: Vec<&'a T::Item>, _com_: Vec<usize>, } impl<'a, T: Iterator> Combination<'a, T> { pub fn new (_obj_: &'a mut T, many: usize) -> Combination<'a, T> { let mut r = Combination::<'a, T> { _obj_items_ : Vec::<&'a T::Item>::with_capacity(_obj_.by_ref().count()), _com_ : Vec::<usize>::with_capacity(many), }; r._com_.append(&mut (0..many).collect()); /* filling vector with _obj_ elements. */ for e in _obj_.by_ref() { r._obj_items_.push(&e); } r } }
我原本认为使用_obj_.by_ref()(注释下方的循环中)会遍历迭代器的元素,但怀疑它实际遍历的是包含元素的迭代器项。请问我的理解是否正确?如何修改代码以正确存储实际元素的引用?
解答
首先纠正你的误解:by_ref()本身不会改变迭代器遍历的内容,它只是把迭代器包装成&mut I类型的引用,这样调用消耗迭代器的方法(比如count())时,不会直接消耗原迭代器,原迭代器本身还能继续使用。
但你的代码有两个核心问题:
- 迭代器已被耗尽:初始化
_obj_items_容量时调用了_obj_.by_ref().count(),这个方法会遍历迭代器所有元素,直接耗尽了迭代器。所以后续的for e in _obj_.by_ref()循环不会有任何元素可以遍历,_obj_items_会是空的。 - 引用生命周期不匹配:就算迭代器没被耗尽,循环里
push(&e)时,e是迭代器每次返回的临时元素,它的生命周期仅在当前循环迭代内有效,无法存储到生命周期为'a的Vec中——Rust的借用规则不允许这种临时引用长期存活。
要解决问题,有两种常见方案:
方案一:直接存储元素所有权(更简单)
如果场景允许持有元素所有权,不需要保留原迭代器的元素,可以把结构体改成存储Vec<T::Item>:
pub struct Combination<T> { _obj_items_: Vec<T>, _com_: Vec<usize>, } impl<T> Combination<T> { pub fn new(mut obj: impl Iterator<Item = T>, many: usize) -> Self { let obj_items = obj.collect(); let com = (0..many).collect(); Combination { _obj_items_: obj_items, _com_: com, } } }
方案二:存储元素引用(需保证原数据源生命周期足够)
如果必须存储引用,需要确保原数据源的生命周期至少和结构体一样长,且不能直接从迭代器收集临时引用——要先把元素存到拥有所有权的容器(比如Vec<T>)中,再让结构体持有该容器的引用:
pub struct Combination<'a, T> { _obj_items_: &'a [T], _com_: Vec<usize>, } impl<'a, T> Combination<'a, T> { pub fn new(items: &'a [T], many: usize) -> Self { let com = (0..many).collect(); Combination { _obj_items_: items, _com_: com, } } } // 使用示例: // let items = vec![1,2,3,4]; // let comb = Combination::new(&items, 2);
另外,原代码中by_ref()的使用是多余的——你已经持有&'a mut T类型的引用,直接调用count()或遍历即可,by_ref()主要用于拥有迭代器所有权、不想直接消耗它的场景。
内容的提问来源于stack exchange,提问作者Mr.Barbo
相关产品推荐
相关产品推荐

