作为输入参数
虽然 Rust 无需类型说明就能在大多数时候完成变量捕获,但在编写函数时,这种模糊写法是不允许的。当以闭包作为输入参数时,必须指出闭包的完整类型,它是通过使用以下 trait
中的一种来指定的。其受限制程度按以下顺序递减:
Fn
:表示捕获方式为通过引用(&T
)的闭包FnMut
:表示捕获方式为通过可变引用(&mut T
)的闭包FnOnce
:表示捕获方式为通过值(T
)的闭包
译注:顺序之所以是这样,是因为
&T
只是获取了不可变的引用,&mut T
则可以改变变量,T
则是拿到了变量的所有权而非借用。
对闭包所要捕获的每个变量,编译器都将以限制最少的方式来捕获。
译注:这句可能说得不对,事实上是在满足使用需求的前提下尽量以限制最多的方式捕获。
例如用一个类型说明为 FnOnce
的闭包作为参数。这说明闭包可能采取 &T
,&mut T
或 T
中的一种捕获方式,但编译器最终是根据所捕获变量在闭包里的使用情况决定捕获方式。
这是因为如果能以移动的方式捕获变量,则闭包也有能力使用其他方式借用变量。注意反过来就不再成立:如果参数的类型说明是 Fn
,那么不允许该闭包通过 &mut T
或 T
捕获变量。
在下面的例子中,试着分别用一用 Fn
、FnMut
和 FnOnce
,看看会发生什么:
参见:
std::mem::drop
, Fn
, FnMut
, 和 FnOnce