Rust中FnMut类型的参数是否为引用类型?
Rust中FnMut类型的参数是否为引用类型?
嘿,我来帮你把这个问题掰明白!你一开始写的那段代码编译失败,核心原因其实和「FnMut是不是引用类型」关系不大,而是所有权转移在搞鬼~
先把你最初的代码贴出来:
fn main() { let mut x = 0; let f = || x += 1; call_me(f); f(); println!("x = {x}"); } fn call_me<F>(f: F) where F: FnMut(), { f(); }
你看,这里call_me的参数f: F是按值接收的——也就是说,当你把闭包f传给call_me的那一刻,这个闭包的所有权就被彻底移交给函数了。函数执行完之后,闭包就被销毁了,所以你后面再尝试调用f(),编译器当然会报错:“你在使用一个已经被移走所有权的变量”。
后来你跟着编译器提示修改,应该是调整了参数的传递方式对吧?正确的改法应该是让call_me接收闭包的可变引用,这样闭包的所有权还牢牢握在main函数里,用完之后还能继续调用。比如修正后的代码大概是这样:
fn main() { let mut x = 0; let mut f = || x += 1; // 这里要给闭包加mut,因为后续要以可变引用传递它 call_me(&mut f); f(); println!("x = {x}"); // 最后会输出x = 2,完美运行~ } fn call_me<F>(f: &mut F) where F: FnMut(), { f(); }
回到你的核心问题:FnMut本身不是引用类型,它是Rust里描述闭包能力的一个trait——表示这个闭包可以被可变地调用(也就是能修改捕获的变量)。你之前的困惑,其实是把「函数参数的传递方式」和「闭包trait的类型」搞混了:FnMut闭包既可以按值传递,也可以按可变引用传递,完全取决于你怎么定义函数的参数签名。
简单总结一下:如果想在函数调用后还能继续使用闭包,就别把闭包的所有权传出去,用可变引用传递给函数就好啦!
备注:内容来源于stack exchange,提问作者Daniel Walker
相关产品推荐
相关产品推荐

