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是为所有Iterators 定义的方法.它允许您查看每个元素并返回与谓词匹配的元素.问题:如果迭代器产生不可复制的值,那么将值传递给谓词将导致无法从中返回它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 .. 可以工作,因为这只是在没有移动任何东西的情况下到达引用内部.
| 归档时间: |
|
| 查看次数: |
576 次 |
| 最近记录: |