Reference “和”的目的是什么在循环变量之前?

Reference “和”的目的是什么在循环变量之前?,reference,rust,pattern-matching,destructuring,ampersand,Reference,Rust,Pattern Matching,Destructuring,Ampersand,列表中的代码&i中的&code>的目的是什么?如果我删除&,它会在最大=I中产生错误,因为它们的类型不匹配(其中I是&32,而I是i32)。但是&i如何将i转换为i32 fn最大(列表:&[i32])->i32{ println!(“{:?}”,列表); 让mut最大=列表[0]; 列表中的for&i{ 如果我>最大的{ 最大=i; } } 最大的 } fn main(){ 让hey=vec![1,3,2,6,90,67788,12,34,54,32]; println!(“最大的数字是:{}”

列表中的代码
&i中的
&code>的目的是什么?如果我删除
&
,它会在
最大=I
中产生错误,因为它们的类型不匹配(其中
I
&32
,而
I
i32
)。但是
&i
如何将
i
转换为
i32

fn最大(列表:&[i32])->i32{
println!(“{:?}”,列表);
让mut最大=列表[0];
列表中的for&i{
如果我>最大的{
最大=i;
}
}
最大的
}
fn main(){
让hey=vec![1,3,2,6,90,67788,12,34,54,32];
println!(“最大的数字是:{}”,最大的(&hey));
}

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

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

4 |嘿=&&x;
|^^^应为i32,找到(&i32)
|
=注意:应为'i32'类型`
找到类型`&&i32`

因此,通常当您对列表中的i使用
时,循环变量
i
的类型为
&i32

但是,当您在列表中为&i使用
时,您并没有取消引用任何内容,而是使用模式匹配来显式地分解引用,这将使
i
仅为
i32
类型

请参阅有关for-loop变量和我们在这里使用的参数的Rust文档。另请参见上的“锈蚀示例”一章

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

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



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

这是分解的效果。我不会在这里完全描述该功能,但简而言之:

在许多语法上下文中(
let
bindings、
for
循环、函数参数等),Rust需要一种“模式”。此模式可以是一个简单的变量名,但也可以包含一些“解构元素”,如
&
。Rust会将一个值绑定到此模式。一个简单的例子如下:

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

这适用于两种结构,包括阵列:

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

不出所料,这也适用于参考

设foo=0u32;
设r=&foo;
让&c=&foo;
这里,
foo
具有类型
u32
,因此表达式
&foo
具有类型
&u32
r
的类型也是
&u32
,因为它是一个简单的
let
绑定。然而,
c
的类型是
u32
!这是因为“引用已被模式分解/删除”

一个常见的误解是模式中的语法与表达式中相同语法的效果完全相反如果变量
a
的类型为
[T;1]
,则表达式
[a]
的类型为
[T;1]
→ 它增加了一些东西。但是,如果将
a
绑定到模式
[c]
,则
y
具有类型
T
→ 它可以移除东西

设a=[true];//`a``的类型:`[bool;1]`
设b=[a];//`b`的类型:`[[bool;1];1]`
设[c]=a;//'c'的类型:`bool`
这也解释了你的问题:

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

fn main() {
    let mut hey: i32 = 32;
    let x: i32 = 2;
    hey = &&x;
}
fn main(){
让mut-hey:i32=32;
设x:i32=2;
嘿=&&x;
}
因为您在表达式端使用了
&
,它在表达式端添加了一层引用


关于循环的最后一点:当迭代一个切片时(就像您在这里所做的),迭代器会产生对切片元素的引用。因此,对于列表{}
中的i,
i
的类型为
&i32
。但赋值
最大=i
需要在右侧安装一个
i32
。您可以通过两种方式实现这一点:通过解引用操作符
*
(即
最大=*i;
)解引用
i
)或在循环模式中分解引用(即
for&i in list{}


相关问题:


与您的问题无关,但函数可以重写为
list.iter().copied().max().expect(“空列表”)
。可能对你有用。是相关的。谢谢你这么清楚的回答。我认为将解构视为代数“取消”操作可能会有所帮助。例如,在
let&c=&foo
-如果“取消”
&
,则
c
设置为
foo
。“c的参考设置为foo的参考”,因此
c
设置为
foo
。感谢您的帮助