为什么嵌套迭代器闭包不会复制外部作用域的值

Kor*_*nel 8 closures rust borrow-checker

我正在尝试使用嵌套迭代器,其中内部迭代器使用外部迭代器中的值.

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(|b|{
        a + b
    })
});
Run Code Online (Sandbox Code Playgroud)

错误:a活不够久

    (0..10).map(|b|{
                ^^^
Run Code Online (Sandbox Code Playgroud)

注意:引用必须对方法调用有效...

如果我移动内部闭包(move |b|{),这会编译,但我不明白为什么它是必要的,因为它a是一个整数,可以被复制而不是移动.

mca*_*ton 7

这两个flat_mapmap懒惰.内部map不会a立即使用,但会尝试"保存"它以便以后需要时借用a.但由于a外部封闭是本地的,并且您返回map结果,借用将变得无效.您需要使用内部迭代器:

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(|b|{
        a + b
    }).collect::<Vec<_>>()
});
Run Code Online (Sandbox Code Playgroud)

当然这不是有效的,内部封闭"保持"会好得多a.你可以通过将内部封闭标记为move:

vec![0;10].iter().flat_map(|&a| {
    (0..10).map(move |b|{
        a + b
    })
});
Run Code Online (Sandbox Code Playgroud)

通常,编译器不允许你这样做,因为flat_map闭包不拥有a,它只是对它的引用.但是,由于Rust中的数字类型(如isize)实现了Copy特征,编译器将复制a而不是尝试移动它,从而提供所需的行为.请注意,这也是您被允许取消引用a(使用|&a|)的原因flat_map; 通常这需要拥有a,而不仅仅是对它的引用(这是.iter()产量).