【问题标题】:What's the difference between filter(|x|) and filter(|&x|)?filter(|x|) 和 filter(|&x|) 有什么区别?
【发布时间】:2015-08-24 17:46:02
【问题描述】:

Rust Book 中有一个在迭代器上调用filter() 的示例:

for i in (1..100).filter(|&x| x % 2 == 0) {
    println!("{}", i);
}

下面有一个解释,但我无法理解:

这将打印 1 到 100 之间的所有偶数。 (请注意,因为过滤器不消耗被迭代的元素,它传递一个对每个元素的引用,因此过滤器谓词使用 &x 模式来提取整数本身。)

但这不起作用:

for i in (1..100).filter(|&x| *x % 2 == 0) {
    println!("i={}", i);
}

为什么闭包的参数是引用|&x|,而不是|x|?以及使用|&x||x|有什么区别?

我知道使用引用 |&x| 更有效,但我对不必使用 *x 取消引用 x 指针这一事实感到困惑。

【问题讨论】:

    标签: closures rust


    【解决方案1】:

    当用作模式匹配时(闭包和函数参数也是模式匹配),& 绑定到一个引​​用,使变量成为 dereferenced 值.

    fn main() {
        let an_int: u8 = 42;
        // Note that the `&` is on the right side of the `:`
        let ref_to_int: &u8 = &an_int; 
        // Note that the `&` is on the left side of the `:`
        let &another_int = ref_to_int;
        let () = another_int;
    }
    

    有错误:

    error: mismatched types:
     expected `u8`,
        found `()`
    

    如果您查看您的案例的错误消息,则表明您无法取消引用它,因为它不是参考

    error: type `_` cannot be dereferenced
    

    我不必使用 *x 取消引用 x 指针。

    那是因为您在模式匹配中隐式取消引用它。

    我了解使用参考 |&x|效率更高

    如果这是真的,那么除了引用之外就没有理由使用任何东西了!也就是说,引用需要额外的间接来获取真实数据。有一些可衡量的分界点,按值传递项目比传递对它们的引用更有效。

    如果是这样,为什么使用|x| 不会引发错误?根据我使用 C 的经验,我希望在这里收到一个指针。

    你确实做到了,以 reference 的形式。 x 是对(在此示例中)i32 的引用。但是,% 运算符是由 trait Rem 提供的,它是为所有引用/值对实现的:

    impl Rem<i32> for i32
    impl<'a> Rem<i32> for &'a i32
    impl<'a> Rem<&'a i32> for i32
    impl<'a, 'b> Rem<&'a i32> for &'b i32
    

    这使您无需显式取消引用它。

    或者Rust是否在这里隐式地在堆栈上分配原始x的值的副本?

    它强调这样做。事实上,这样做是不安全的,除非迭代的项目实现了Copy(或者可能是Clone,在这种情况下它也可能很昂贵)。这就是为什么引用被用作闭包参数的原因。

    【讨论】:

    • 所以let &amp;x = my_pointer实际上是let x = *my_pointer的替代品,而且它也适用于函数参数声明?如果是这样,为什么使用|x| 不会引发错误?根据我对 C 的经验,希望在这里收到一个指针。或者 rust 是否在这里隐式地在堆栈上分配了原始 x 的值的副本?
    • 哦,我还有很多东西要学 :) 谢谢 - 我现在清楚多了!
    猜你喜欢
    • 1970-01-01
    • 2011-10-17
    • 2020-01-01
    • 2020-07-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-14
    相关资源
    最近更新 更多