为什么在这种情况下需要引用/借用?

4

我是 Rust 的新手,只是在尝试一些代码:

fn array_leaders(arr: &[i32]) -> Vec<i32> {
    let mut res = Vec::new();
    for (i, left) in arr.iter().enumerate() {
        let right = arr.iter().skip(i+1).sum();
        if left > right { res.push(*left) };
    }
    res
}

导致以下错误:

error[E0277]: the trait bound `&i32: Sum<&i32>` is not satisfied
    --> src/lib.rs:5:42
     |
5    |         let right = arr.iter().skip(i+1).sum();
     |                                          ^^^ the trait `Sum<&i32>` is not implemented for `&i32`

现在,我已经想到了一个方法,就是在if语句中的正确变量右边添加一个&符号:

        if left > &right { res.push(*left) };

这解决了问题。不过我想知道为什么。

1个回答

4
这是因为left具有&i32类型(通过.iter()生成),但right具有i32类型(通过sum()生成)。
我们可以将*left与两个i32中的right进行比较。
Rust还通过引用启用了比较:left&right(两个&i32)。
比较的两侧必须具有相同的间接级别。
下面的简短示例试图说明这一点。
此外,正如评论中所述,当存在一些选择时,Rust会尝试推断不严格强制执行的类型。 在这里,left的类型由.iter()强制执行,但sum()的返回类型可以被推断。 然后,Rust尝试找到与&i32匹配的sum()实现,因为此结果将与&i32left)进行比较。 在这里找不到,因此出错。
fn main() {
    let a = 5;
    for b in 3..=7 {
        let r_a = &a;
        let r_b = &b;
        let cmp1 = a < b;
        let cmp2 = r_a < r_b;
        let cmp3 = *r_a < *r_b;
        println!("{} < {} --> {} {} {}", a, b, cmp1, cmp2, cmp3);
    }
}
/*
5 < 3 --> false false false
5 < 4 --> false false false
5 < 5 --> false false false
5 < 6 --> true true true
5 < 7 --> true true true
*/

2
要非常清楚,错误发生在声明right的那一行,因为Rust试图使所有特征对齐,但解析失败了。它并没有说“我无法比较i32&i32”。它说:“我需要一个&i32,所以我尝试让sum返回一个&i32,但它不起作用”,因为这是编译器的思考方式。 - Silvio Mayolo
非常感谢,让事情变得更加清晰! - Martin

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接