在 for 循环中引用/取消引用向量元素



在下面的代码中,我想在迭代后保留number_list,因为for默认使用的.into_iter()会消耗。因此,我假设n: &i32和我可以通过取消引用来获得n的值。

fn main() {
let number_list = vec![24, 34, 100, 65];
let mut largest = number_list[0];
for n in &number_list {
if *n > largest {
largest = *n;
}
}
println!("{}", largest);
}

有人向我透露,我们可以将&n用作"模式",而不是这个:

fn main() {
let number_list = vec![24, 34, 100, 65];
let mut largest = number_list[0];
for &n in &number_list {
if n > largest {
largest = n;
}
}
println!("{}", largest);
number_list;
}

我的困惑(请记住,我没有涵盖模式(是我希望自n: &i32以来,然后&n: &&i32而不是解析为值(如果双引用是可能的(。为什么会发生这种情况,&的含义是否因上下文而异?

将引用视为一种容器会有所帮助。为了进行比较,请考虑Option,我们可以使用模式匹配"解包"值,例如在if let语句中:

let n = 100;
let opt = Some(n);
if let Some(p) = opt {
// do something with p
}

我们调用SomeNone构造函数Option,因为它们各自产生一个类型为Option的值。同样,您可以将&视为引用的构造函数。语法是对称的:

let n = 100;
let reference = &n;
if let &p = reference {
// do something with p
}

您可以在将值绑定到变量的任何位置使用此功能,这种情况随处可见。例如:

  1. if let,如上

  2. match表达式:

    match opt {
    Some(1) => { ... },
    Some(p) => { ... },
    None    => { ... },
    }
    match reference {
    &1 => { ... },
    &p => { ... },
    }
    
  3. 在函数参数中:

    fn foo(&p: &i32) { ... }
    
  4. 循环:

    for &p in iter_of_i32_refs {
    ...
    }
    

可能还有更多。

请注意,最后两个不适用于Option,因为如果找到None而不是Some,它们会感到恐慌,但这不会发生在引用中,因为它们只有一个构造函数&

&的含义是否因上下文而异?

希望你能&解释为构造函数而不是运算符,那么你会看到它的含义不会改变。这是 Rust 的一个非常酷的功能,你可以在表达式的右侧使用构造函数来创建值,在左侧使用构造函数来拆解(解构(。

与其他语言(C++(不同,在这种情况下&n不是引用,而是模式匹配,这意味着这是需要引用的。
与此相反的是ref n,它会给你&&i32类型。

关闭也是如此,例如

(0..).filter(|&idx| idx < 10)...

请注意,这将移动变量,例如,你不能对不实现Copy特征的类型执行此操作。

我的困惑(请记住,我没有涵盖模式(是我希望既然 n: &i32,那么 &n: &&i32 而不是解析为值(如果双引用是可能的(。为什么会发生这种情况,&&的含义是否因上下文而异?

当你做模式匹配时(例如当你写for &n in &number_list时(,你不是说n是一个&i32,而是说&n(模式(是一个&i32(表达式(,编译器从中推断n是一个i32

类似的情况发生在各种模式上,例如,当if let Some (x) = Some (42) { /* … */ }中的模式匹配时,我们说Some (x)Some (42),因此x是42。

最新更新