FnOnce,FnMut和Fn
继承结构
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(());
}
FnOnce,FnMut和Fn的更多相关文章
- 【译】理解Rust中的Futures(二)
		原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ... 
- 闭包类型(Fn,FnMut,FnOnce)和move关键字
		move关键字是强制让环境变量的所有权转移到闭包中而不管是不是发生了所有权的转移 move关键字和匿名函数是否是FnOnce没有必然联系,之和匿名函数体有关 当匿名函数体里转移了环境变量的所有权的时候 ... 
- JavaScript中fn()和return fn()
		看博客时,注意到return的重要性 参考:http://www.cnblogs.com/raoyunxiao/p/5644032.html 看似反常的例子: var i = 0; function ... 
- ubuntu系统(华硕笔记本)屏幕亮度用Fn控制的调节设置
		亲测配置: 系统:Linux lite 3.2 x86_64(Ubuntu其他版本可参考修改) 笔记本:华硕(asus)1201N 达到的效果: 可以正常使用Fn+F5调暗,Fn+F6调亮. 设置步骤 ... 
- 设置Fn键  笔记本直接按F1-F12 无须按Fn键 Fn+F12改F12(联想小新300为例)
		最近公司给配的笔记本联想小新300 80RT i7-6500U 4G内存 500G机械,后加装120G固态+4G内存 这样就感觉还不错了. 在使用这本子的时候,去了Win10,强行装了Win7.无线 ... 
- jquery.fn.extend与jquery.extend--(初体验二)
		1.jquery.extend(object); 为扩展jQuery类本身.为类添加新的方法. jquery.fn.extend(object);给jQuery对象添加方法. $.extend({ a ... 
- jQuery为开发插件提拱了两个方法:jQuery.fn.extend();  jQuery.extend();
		jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(); jQuery.extend(); jQuery.fn jQuery.fn = jQuery.prototype ... 
- Jquery揭秘系列:实现$.fn.extend 和$.extend函数
		前面我们扩展了bind方法和ready函数,这次我要讲一下$.fn.extend 和$.extend函数. 其他的不多说,直接切入主题吧! 先来看看这两个函数的区别: $.fn.extend是为查询的 ... 
- java Fn键
		需求分析 我想开机禁用触摸板. 方案设计 安装驱动:比较麻烦,驱动也不一定支持开机禁用触摸板. 编程实现,让一段代码开机禁用触摸板 编程实现也分好几种方法: 使用windows API禁用触摸板,这需 ... 
随机推荐
- 机器学习实战-k近邻算法
			写在开头,打算耐心啃完机器学习实战这本书,所用版本为2013年6月第1版 在P19页的实施kNN算法时,有很多地方不懂,遂仔细研究,记录如下: 字典按值进行排序 首先仔细读完kNN算法之后,了解其是用 ... 
- 微信H5页面唤醒APP并传参跳转uniapp
			主要实现是利用微信内置浏览器支持的<wx-open-launch-app>开放标签可以让你的H5网页拉起APP 在链接https://developers.weixin.qq.com/ ... 
- 探索 Python/Django 支持分布式多租户数据库,如 Postgres+Citus
			在 确定分布策略 中,我们讨论了在多租户用例中使用 Citus 所需的与框架无关的数据库更改. 在这里,我们专门研究如何借助 django-multitenant 库将多租户 Django 应 用程序 ... 
- Java泛型类型擦除问题
			以前就了解过Java泛型的实现是不完整的,最近在做一些代码重构的时候遇到一些Java泛型类型擦除的问题,简单的来说,Java泛型中所指定的类型在编译时会将其去除,因此List 和 List 在编译成字 ... 
- mybatis plus 增删改自动填充字段值
			说明 本文实现以下需求效果 创建数据时自动填充 createUserId 和 createTime 更新数据时自动填充 updateUserId 和 updateTime(每次修改都自动填充新的 up ... 
- 手把手教你使用 Spring Boot 3 开发上线一个前后端分离的生产级系统(一) - 介绍
			项目简介 novel 是一套基于时下最新 Java 技术栈 Spring Boot 3 + Vue 3 开发的前后端分离的学习型小说项目,配备详细的项目教程手把手教你从零开始开发上线一个生产级别的 J ... 
- DML数据操作语言
			DML数据操作语言 用来对数据库中表的数据记录进行更新.(增删改) 插入insert -- insert into 表(列名1,列名2,列名3...) values (值1,值2,值3...):向表中 ... 
- 硬件开发笔记(四):硬件开发基本流程,制作一个USB转RS232的模块(三):设计原理图
			前者 前面建立好的基础的元器件,下面开始设计原理图. 需求 USB转RS232,输出RS232 可以选择性输出5V的TTL 可以选择性输出3.3V的TTL 设计原理图 步骤一:CH340G ... 
- 如何提高访问 GitHub 的速度
			更新记录 本文迁移自Panda666原博客,原发布时间:2021年5月11日. 因为一些特殊的原因,国内访问Github的速度确实比较慢.国内访问Github经常会出现连接不上.图片加载不出来.文件无 ... 
- Typora图片与阿里云OSS图床的结合之旅
			图床? 专门用于存放图片,并允许用户通过独一的外链进行特定图片资源的访问 为什么是阿里云OSS(Object Storage Service) 码云开源需要审核,已经不能作为免费的图床使用(2022年 ... 
