继承结构

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(());
}

最新文章

  1. Android 底部弹出Dialog(横向满屏)
  2. java中filter的用法 内部资料 请勿转载 谢谢合作
  3. 自定义log日志
  4. Codeforces Round #249 (Div. 2) A题
  5. javascript的关于刷新页面给出提示框的代码
  6. 跟我学 NHibernate (二)
  7. ffmpeg 按时间戳读取文件 -re
  8. 【转】eclipse android 设置及修改生成apk的签名文件 -- custom debug keystore
  9. 名字修饰约定extern &quot;C&quot;与extern &quot;C++&quot;浅析
  10. 读书时间《JavaScript高级程序设计》一:基础篇
  11. PowerDesigner制作UMI图
  12. 关于HTTP以及TCP
  13. MyBatis:SQL语句中的foreach的详细介绍
  14. Net Core平台灵活简单的日志记录框架NLog+SqlServer初体验
  15. 1.个人项目 Individual Project
  16. 设计模式-结构型模式,python组合模式
  17. [转]RabbitMQ系列(一):Windows下RabbitMQ安装及入门
  18. BZOJ 1799 - [AHOI2009]self 同类分布 - 枚举 数位DP
  19. HTML5 桌面提示
  20. Linux中连接mysql执行sql文件

热门文章

  1. Android 4.4系统,User模式adb默认开启,取消授权,开启root调试记录
  2. ubuntu 获取 gateway 网关 ip
  3. c# DateTime 格式化输出字符串
  4. Redis系列:深刻理解高性能Redis的本质
  5. 如何实现将拖动物体限制在某个圆形内--实现方式vue3.0
  6. 个人冲刺(一)——体温上报app(二阶段)
  7. MongoDB 分片集群
  8. CenterNet训练时黑白图片不能画框的问题
  9. React简单教程-4-事件和hook
  10. Tarjan算法模板(USACO03FALL受欢迎的牛)