在下面的代码中,我想在迭代后保留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
}
我们调用Some
和None
构造函数来Option
,因为它们各自产生一个类型为Option
的值。同样,您可以将&
视为引用的构造函数。语法是对称的:
let n = 100;
let reference = &n;
if let &p = reference {
// do something with p
}
您可以在将值绑定到变量的任何位置使用此功能,这种情况随处可见。例如:
if let
,如上match
表达式:match opt { Some(1) => { ... }, Some(p) => { ... }, None => { ... }, } match reference { &1 => { ... }, &p => { ... }, }
在函数参数中:
fn foo(&p: &i32) { ... }
循环:
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。