FnOnce,FnMut和Fn
2024-09-07 10:22:46
继承结构
FnOnce
FnMut: FnOnce
Fn: FnMut
FnOnce就是说会转移闭包捕获变量的所有权,在闭包前加上move关键字可以限定此闭包为FnOnce
move关键字是强制让环境变量的所有权转移到闭包中而不管是不是发生了所有权的转移
#![feature(core_intrinsics)]
fn print_type_of<T>(_: T) {
println!("{}", unsafe { std::intrinsics::type_name::<T>() });
} fn main() {
let i = vec![1];
let x: Box<dyn FnOnce() -> ()> = Box::new(move || {
// print_type_of(i);
println!("{:?}", i);
});
x();
println!("{:?}", i);
}
上面代码会报错
当然如果i是一个实现呢Copy的变量就不会报错了,因为Copy变量会自动复制而不会转移所有权
不用move关键字,只要闭包类转移了环境变量的所有权,闭包就只会实现FnOnce
#![feature(fn_traits)]
fn main() {
let mut i = vec![1];
let mut fn1 = || {
i
};
fn1.call_mut(());
fn1.call(());
fn1.call_once(());
}
上面代码报错,因为fn1只实现了call_once方法
FnMut就是改变了捕获变量
fn main() {
let mut i = vec![1]; let mut x: Box<dyn FnMut() -> ()> = Box::new(|| {
i.push(2);
}); x();
}
这个代码里dyn FnMut() -> ()可以改为dyn FnOnce() -> (),但是不能改为dyn Fn() -> ()。因为实例是一个FnMut,只能往上转型,不能往下转型
FnMut捕获是按可变借用捕获的,所以FnMut捕获的变量在闭包外也是不能使用的,即使被捕获的变量实现了Copy
let mut i = 1; let mut x: Box<dyn FnMut() -> ()> = Box::new(|| {
i = i + 1;
}); x();
println!("{}", 1 + i);
上面代码的错误简化下就是
fn test(ii: &mut i32, i: i32) {} fn main() {
let mut i = 1;
let ii = &mut i;
test(ii, i);
}
如果需要变量在FnMut后还能使用,需要用Mutex模拟。用Mutex模拟后,闭包也不再是FnMut了,而是Fn
use std::sync::Mutex; fn main() {
let mut i = Mutex::new(1); let mut x: Box<dyn Fn() -> ()> = Box::new(|| {
let mut ii = i.lock().unwrap();
*ii = 2;
}); x();
let iii = i.lock().unwrap();
println!("{}", iii);
}
一个啥也不干的闭包就是Fn了,Fn以不可变借用捕获环境变量
fn main() {
let x: Box<dyn Fn() -> ()> = Box::new(|| {
});
}
Fn能调用FnMut和FnOnce的方法
#![feature(fn_traits)]
fn main() {
let mut fn1 = || {};
fn1.call_mut(());
fn1.call_once(());
}
最新文章
- Android 底部弹出Dialog(横向满屏)
- java中filter的用法 内部资料 请勿转载 谢谢合作
- 自定义log日志
- Codeforces Round #249 (Div. 2) A题
- javascript的关于刷新页面给出提示框的代码
- 跟我学 NHibernate (二)
- ffmpeg 按时间戳读取文件 -re
- 【转】eclipse android 设置及修改生成apk的签名文件 -- custom debug keystore
- 名字修饰约定extern ";C";与extern ";C++";浅析
- 读书时间《JavaScript高级程序设计》一:基础篇
- PowerDesigner制作UMI图
- 关于HTTP以及TCP
- MyBatis:SQL语句中的foreach的详细介绍
- Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验
- 1.个人项目 Individual Project
- 设计模式-结构型模式,python组合模式
- [转]RabbitMQ系列(一):Windows下RabbitMQ安装及入门
- BZOJ 1799 - [AHOI2009]self 同类分布 - 枚举 数位DP
- HTML5 桌面提示
- Linux中连接mysql执行sql文件