如何设置盒装闭合捕获`self`的生命周期?

Ben*_*son 3 iterator lifetime rust

我想返回一个迭代器(特别是a Filter).我使用了之前的答案,建议返回一个盒装迭代器.问题是我的过滤器捕获self并得到:

错误:闭包可能比当前函数更长,但它借用self了当前函数所拥有的函数

但我认为我是明确的,self有生命'a,所以Box我回来了:

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
    Box::new( (0..32).filter( |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}
Run Code Online (Sandbox Code Playgroud)

这是为了简化我的第一次尝试,我创建了FooIterator一个以self基本相同的方式拥有引用的new .

如果我使用大多数相同的语法来简单地捕获self作为成员引用它工作正常:

struct Foo { junk: i32 }
struct FooIterator<'a> { foo: &'a Foo }
impl Foo {
    fn foo<'a>(&'a self) -> Box<FooIterator<'a>> {
        Box::new( FooIterator { foo: self } )
    }       
}
Run Code Online (Sandbox Code Playgroud)

Fra*_*gné 5

你得到一个错误,因为你的闭包收到一个引用self,它本身就是一个引用.但是,由于引用指向局部变量,因此只要函数返回,该引用就会变为无效.

要解决此问题,请move在关闭之前添加关键字.这指示编译器在闭包中移动闭合变量,而不是将对这些变量的引用传递给闭包.

fn occupied_iter_x<'a>(&'a self) -> Box<Iterator<Item=i32> + 'a> {
    Box::new( (0..32).filter(move |&pos| match self.at(pos) { Occupied::Empty => false, _ => true } ) )
}
Run Code Online (Sandbox Code Playgroud)

  • @BenJackson,如果不使用`move`关键字,闭包将通过引用捕获其环境(在这种情况下,环境将包含对&self的引用,即双引用).如果这样做,它将按值捕获它.这就是Rust的封闭工作方式. (2认同)