【问题标题】:Referencing / dereferencing a vector element in a for loop在 for 循环中引用/取消引用向量元素
【发布时间】:2019-02-11 16:13:40
【问题描述】:

在下面的代码中,我想在迭代之后保留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,而不是解析为值(如果甚至可以使用双重引用)。为什么会发生这种情况,& 的含义是否因上下文而异?

【问题讨论】:

    标签: syntax reference rust pattern-matching


    【解决方案1】:

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

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

    我们为Option 调用SomeNone 构造函数,因为它们都产生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,它们会感到恐慌,但引用不会发生这种情况,因为它们只有一个构造函数,@ 987654339@.

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

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

    【讨论】:

      【解决方案2】:

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

      当您进行模式匹配时(例如,当您编写for &n in &number_list 时),您并不是说n&i32,而是说&n(模式)是@987654325 @(表达式),编译器从中推断出ni32

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

      【讨论】:

        【解决方案3】:

        与其他语言 (C++) 不同,在这种情况下,&n 不是引用,而是模式匹配,这意味着 this 需要引用。
        与此相反的是ref n,它将为您提供&&i32 作为一种类型。

        闭包也是如此,例如

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

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

        【讨论】:

          猜你喜欢
          • 2020-01-31
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-05-31
          • 1970-01-01
          • 2018-07-28
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多