很明显,迭代器传递引用以避免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
语义,对吧?
答案 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);
}
}