Rust可变闭包使用疑惑:为何两种场景mut修饰要求不同?
Rust闭包的
mut声明困惑:为什么直接调用要mut,传给函数不用? 核心原因:闭包的调用依赖自身的可变性
闭包捕获可变环境时,它的调用逻辑(对应FnMut trait的call_mut方法)要求&mut self权限。这直接导致两种场景的差异:
- 如果你直接在当前作用域调用闭包,必须拥有闭包的可变借用权限——要么把闭包变量声明为
mut,要么调用时显式可变借用(比如(&mut func)())。 - 如果你把闭包传给其他函数,只要函数参数接受
FnMut类型,函数内部会自动以可变方式处理闭包,不需要你在外部声明mut。
第一个示例:直接调用闭包需要mut
看你的第一段代码:
fn main() { let mut list = vec![1, 2, 3]; let mut borrows_mutably = || list.push(7); borrows_mutably(); }
这个闭包捕获了list的可变引用,属于FnMut() -> ()类型。当你直接调用borrows_mutably()时,本质是调用它的call_mut(&mut self)方法——这要求你对闭包变量拥有可变权限,所以必须把borrows_mutably声明为mut。
如果不声明mut,编译器会报错,因为你试图对一个不可变绑定的闭包执行可变操作(调用需要&mut self的方法)。
第二个示例:传给函数时无需mut
再看第二段代码:
fn main() { let mut num_ops = 0; let func = |r: &i32| { num_ops += 1; r.abs() }; let mut list = [-3, 1, 5]; list.sort_by_key(func); println!("{:?}, {}", list, num_ops); }
sort_by_key的签名是:
pub fn sort_by_key<K, F>(&mut self, mut f: F) where F: FnMut(&T) -> K, K: Ord,
它的参数是mut f: F——函数内部会把传入的闭包绑定为可变变量,因此可以直接调用闭包的call_mut方法,不需要你在外部把func声明为mut。
而如果自己直接调用func(),还是需要func是mut的,因为此时是你在当前作用域调用它的可变方法,必须持有可变权限。
总结
- 闭包是否需要声明为
mut,取决于你在当前作用域中是否需要对闭包执行可变操作(比如直接调用)。 - 当闭包被传给接受
FnMut的函数时,函数会负责处理闭包的可变借用,外部的闭包变量不需要额外声明mut。
内容的提问来源于stack exchange,提问作者Jaime Arboleda Castilla
相关产品推荐
相关产品推荐

