在for循环中引用/解除引用向量元素

问题描述 投票:2回答:3

在下面的代码中,我想在迭代之后保留number_list,因为.into_iter()默认使用的for将消耗。因此,我假设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而不是它解析的价值(如果双重参考甚至可能)。为什么会发生这种情况,&的含义是否因环境而异?

syntax reference rust pattern-matching
3个回答
7
投票

它可以帮助将引用视为一种容器。为了比较,考虑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 { ... }

也许more

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

&的含义是否因环境而异?

希望如果你能将&解释为构造函数而不是运算符,那么你会发现它的含义不会改变。 Rust的一个非常酷的功能是,您可以在表达式的右侧使用构造函数来创建值,并在左侧使用它们将它们分开(解构)。


2
投票

除了其他语言(C ++)之外,&n在这种情况下不是引用,而是模式匹配,这意味着这是期待引用。 与此相反的是ref n,它会给你&&i32作为一种类型。

闭包也是如此,例如

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

请注意,这将移动变量,例如对于没有实现Copy特性的类型,你不能这样做。


2
投票

我的困惑(并记住我没有涵盖模式)是我会期望,因为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。

© www.soinside.com 2019 - 2024. All rights reserved.