循环变量前的“&”的作用是什么?

时间:2019-08-03 14:25:35

标签: reference rust pattern-matching destructuring ampersand

代码&&i in list的目的是什么?如果我删除&,则会在largest = i中产生错误,因为它们的类型不匹配(其中i&32,而i是{{1} }。但是i32如何将&i转换成i

i32

Playground

似乎在某种程度上取消了引用,但是为什么在下面的代码中,它不起作用?

fn largest(list: &[i32]) -> i32 {
    println!("{:?}", list);
    let mut largest = list[0];
    for &i in list {
        if i > largest {
            largest = i;
        }
    }
    largest
}

fn main() {
    let hey = vec![1, 3, 2, 6, 90, 67, 788, 12, 34, 54, 32];
    println!("The largest number is: {}", largest(&hey));
}

它说:

fn main() {
    let mut hey: i32 = 32;
    let x: i32 = 2;
    hey = &&x;
}

2 个答案:

答案 0 :(得分:3)

因此,通常,当您使用for i in list时,循环变量i的类型为&i32

但是当您使用for &i in list时,您并没有取消引用,而是您正在使用模式匹配来明确地解构引用< / strong>,这将使i的类型为i32

请参阅Rust文档,以了解我们在此处使用的for循环变量being a patternreference pattern。另请参见destructuring pointers上的“按示例生锈”一章。

解决此问题的另一种方法是保持i不变,然后将i与对largest的引用进行比较,然后在引用之前取消对i的引用分配给largest

fn largest(list: &[i32]) -> i32 {
    println!("{:?}", list);
    let mut largest = list[0];
    for i in list {
        if i > &largest {
            largest = *i;
        }
    }
    largest
}


fn main() {
    let mut hey: i32 = 32;
    let x: i32 = 2;
    hey = &&x;
}

这根本行不通,因为在这里,您将hey(这是i32)分配给对i32的引用。这与循环变量情况下的模式匹配和解构无关。

答案 1 :(得分:3)

这是破坏 的效果。在这里,我不会完全描述该功能,但总之:

在许多语法上下文中(let绑定,for循环,函数参数...),Rust期望使用“模式”。该模式可以是简单的变量名,但也可以包含一些“解构元素”,例如&。然后Rust将一个值绑定到该模式。一个简单的例子就是这样:

let (a, b) = ('x', true);

在右侧有一个(char, bool)类型的值(元组)。该值绑定到左手模式((a, b))。由于模式中已经定义了“结构”(特别是元组),因此将删除该结构,并将ab绑定到元组的元素。因此,a的类型为charb的类型为bool

这适用于两个结构,包括数组:

let [x] = [true];

同样,在右边,我们有一个[bool; 1]类型的值(一个数组),在左边,我们有一个数组形式的模式。单个数组元素绑定到x,这意味着x的类型为bool不是 [bool; 1]

毫不奇怪,这也可以作为参考!

let foo = 0u32;
let r = &foo;
let &c = &foo;

这里,foo的类型为u32,因此表达式&foo的类型为&u32r的类型也是&u32,因为它是简单的let绑定。 c的类型为u32!这是因为该模式对“引用进行了重构/删除”。

一个常见的误解是模式中的语法与表达式中的语法具有完全相反的效果!如果您拥有类型a的变量[T; 1] ,则表达式[a]的类型为[[T; 1]; 1]→它添加内容。但是,如果将a绑定到模式[c],则yy has the type T`→它会删除

let a = [true];    // type of `a`: `[bool; 1]`
let b = [a];       // type of `b`: `[[bool; 1]; 1]`
let [c] = a;       // type of `c`: `bool`

这也解释了您的问题:

  

似乎在某种程度上取消了引用,但是为什么在下面的代码中它不起作用?

     
fn main() {
   let mut hey:i32 = 32;
   let x:i32 = 2;
   hey = &&x;
}

因为您在表达式侧使用了&,所以在 处添加了一层引用。


最后就是循环:在切片上进行迭代时(如此处所述),迭代器会产生对切片元素的引用。因此,在for i in list {}的情况下,i的类型为&i32。但是分配largest = i;在右侧需要i32。您可以通过两种方式实现此目的:通过取消引用运算符i(即*取消引用largest = *i;或在循环模式中取消引用的结构(即for &i in list {})。


相关问题