Saj*_*uuk 9 reference rust borrowing
我在这里有两个问题.
let a = [1, 2, 3];
assert_eq!(a.iter().find(|&&x| x == 2), Some(&2));
assert_eq!(a.iter().find(|&&x| x == 5), None);
Run Code Online (Sandbox Code Playgroud)
1.为什么&&x
在闭包参数中使用而不仅仅是x
?(我理解"&"正在传递一个对象的引用,但是两次使用它的意思是什么?)
这本书写道:
因为find()接受引用,并且许多迭代器遍历引用,这导致可能令人困惑的情况,其中参数是双引用.您可以在下面的示例中看到此效果,使用&& x.
但我真的不明白.
2.为什么&
用而不是find()
?
DK.*_*DK. 14
a
属于[i32; 3]
; 三个数组i32
.
[i32; 3]
没有实现一个iter
方法,但它确实取消引用&[i32]
.
&[i32]
实现一个iter
生成迭代器的方法.
这个迭代器实现了Iterator<Item=&i32>
.
它使用&i32
而不是i32
因为迭代器必须处理任何类型的数组,并不是所有类型都可以安全地复制.因此,它不是将自身限制为可复制类型,而是通过引用而不是值来迭代元素.
find
是为所有Iterator
s 定义的方法.它允许您查看每个元素并返回与谓词匹配的元素.问题:如果迭代器产生不可复制的值,那么将值传递给谓词将导致无法从中返回它find
.无法重新生成该值,因为迭代器(通常)不可重绕或可重新启动.因此,find
必须将元素传递给谓词by-reference而不是by-value.
因此,如果你有一个实现的迭代器Iterator<Item=T>
,那么Iterator::find
需要一个带有a &T
并返回a 的谓词bool
. [i32]::iter
生成一个实现的迭代器Iterator<Item=&i32>
.因此,Iterator::find
调用数组迭代器需要一个带有a的谓词&&i32
.也就是说,它将谓词传递给指向所讨论元素的指针.
所以如果你要写a.iter().find(|x| ..)
,那x
就是&&i32
.这不能直接相比字面i32
值2
.有几种方法可以解决这个问题.一个是明确地解除引用x
:a.iter().find(|x| **x == 2)
.另一种是使用模式匹配来构造双引用:a.iter().find(|&&x| x == 2)
.在这种情况下,这两种方法完全相同.[1]
至于为什么Some(&2)
使用:因为a.iter()
是在一个迭代&i32
,不是的迭代器i32
.如果您查看文档Iterator::find
,您会看到Iterator<Item=T>
,它会返回一个Option<T>
.因此,在这种情况下,它返回一个Option<&i32>
,所以你需要将它与之进行比较.
[1]:差异只在你谈论非Copy
类型时才有意义.例如,|&&x| ..
不能在a上工作&&String
,因为你必须能够String
从引用后面移出,而这是不允许的.但是,|x| **x ..
可以工作,因为这只是在没有移动任何东西的情况下到达引用内部.