我正在尝试构建一个迭代器,它产生对Vec
的引用。我会尝试解释我的理由,以了解我的缺陷。
我的第一次尝试是让迭代器拥有对象:
pub struct VecIter<T> {
x: Vec<T>,
}
然而,根据Iterator returning items by reference, lifetime issue,这不起作用。上面的答案有两个建议:不要返回引用,或者引用该对象。
引用答案:
对于您具体的,可能是简单的例子,您应该停下来 产生引用,或改变它,以便你的迭代器对象不会 包含你迭代的数据 - 让它只包含一个 参考它,例如&amp;'a [T]甚至像物品&lt;'a,T&gt;。
我想实现第二个选项:即,通过让迭代器包含引用来返回引用。
我已将代码缩减为最简单的版本,我无法编译:
pub struct VecIter<'a, T> where T: 'a {
x: &'a mut Vec<T>,
}
impl<'a, T> VecIter<'a, T> {
fn next_(&'a mut self) -> Option<&'a Vec<T>> {
// do something to modify self.x
Some(self.x)
}
}
pub fn main() {
let mut vec_i = VecIter{x: &mut vec![100,200,300]};
while let Some(x) = vec_i.next_() {
// ...
}
}
我希望上面的代码能够正常工作,因为每个可变的借用只存在于循环体内。所以我的想法是借用循环体的引用,在循环中使用它,并在循环结束时结束借用。
是否可以构建这样的迭代器?即,构建一个迭代器,该迭代器产生对它在next()
中修改的对象的引用?
修改:
在Matthieu M的评论中,有人建议我为此工作:
删除
'a
,以便next_(&'a mut self)
变为next_(&mut self)
也许我理解错误,但我尝试了这个,我得到了以下编译错误。为了避免混淆,这里是我尝试的代码(playground):
<anon>:8:14: 8:20 error: cannot infer an appropriate lifetime for automatic coercion due to conflicting requirements [E0495]
<anon>:8 Some(self.x)
^~~~~~
<anon>:6:5: 9:6 help: consider using an explicit lifetime parameter as shown: fn next_(&'a mut self) -> Option<&'a Vec<T>>
<anon>:6 fn next_(&mut self) -> Option<&'a Vec<T>> {
<anon>:7 // do something to modify self.x
<anon>:8 Some(self.x)
<anon>:9 }
error: aborting due to previous error
playpen: application terminated with error code 101
答案 0 :(得分:1)
以下是您的next_()
方法的修改,似乎有效:
fn next_<'b>(&'b mut self) -> Option<&'b Vec<T>>
where 'a: 'b { ... }
'b
参数将被省略(lifetime elision),因此也可以这样做:
fn next_(&mut self) -> Option<&Vec<T>> { ... }
self
和self.x
的生命周期不同。 我在找出这个不起作用的确切原因时遇到了一些麻烦,但一般来说,你不需要写&'x self
,如果你从来没有'x
永远不是self
类型的参数。
编辑:好的,我现在明白了。我一直忽略self.x
是可变借用Vec
的事实,但您尝试返回不可变引用它。如果self.x
未标记为mut
,则您可以返回Some(self.x)
并将其复制。但是你不能复制一个可变引用,所以它必须重新借用。此外,重新借用(不可变)引用的存在将导致无法调用&mut self
方法或销毁self
直到引用被销毁,因此self
必须比新借用更长。这就是为什么你无法返回&'a Vec<T>
:如果可以的话,就不可能销毁self
。