为什么在这里使用"&&"?

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.这不能直接相比字面i322.有几种方法可以解决这个问题.一个是明确地解除引用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 .. 可以工作,因为这只是在没有移动任何东西的情况下到达引用内部.

  • 谢谢!另外,如果有人不明白什么是***“解引用到``&amp;[i32]```”***,数组``a```可以自动借用为切片` ``&amp;a``` 根据[this](http://rustbyexample.com/primitives/array.html), (4认同)