迭代复制类型

时间:2015-10-29 20:27:17

标签: iterator rust

很明显,迭代器传递引用以避免moving个对象进入迭代器或它的闭包参数,但是复制类型是什么?让我给你看一个小片段:

fn is_odd(x: &&i32) -> bool { *x & 1 == 1 }
// [1] fn is_odd(x: &i32) -> bool { x & 1 == 1 }
// [2] fn is_odd(x: i32) -> bool { x & 1 == 1 }

fn main() {
    let xs = &[ 10, 20, 13, 14 ];

    for x in xs.iter().filter(is_odd) { 
        assert_eq!(13, *x);                     
    }   

    // [1] ...is slightly better, but not ideal
    // for x in xs.iter().cloned().filter(is_odd) { 
    //     assert_eq!(13, x); 
    // }
}

我是正确的,当我们迭代.cloned()&[i32]这样的地方时,&[u8]是首选的,其中涉及额外的间接而不是仅复制微小的数据单元?

但看起来我无法避免传递给is_odd函数的引用。

是否可以通过上述代码段为[2]等更高级别的功能提供filter功能?

假设我明白将非复制类型移动到predicate函数是愚蠢的。但是默认情况下并非所有类型都使用move语义,对吧?

1 个答案:

答案 0 :(得分:4)

  

很明显,迭代器传递了引用

这种一揽子陈述不正确,迭代器不仅能够产生非参考。 filter将提供对闭包的引用,因为它不想将该项的所有权赋予闭包。在您的示例中,您的迭代值为&i32,然后filter提供&&i32

  

有没有办法让上面代码片段的[2]功能适用于像过滤器这样的高级函数?

当然,只需提供一个解除引用的闭包:

fn is_odd(x: i32) -> bool { x & 1 == 1 }

fn main() {
    let xs = &[ 10, 20, 13, 14 ];

    for x in xs.iter().filter(|&&x| is_odd(x)) { 
        assert_eq!(13, *x);                     
    }   
}