继承结构

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的更多相关文章

  1. 【译】理解Rust中的Futures(二)

    原文标题:Understanding Futures in Rust -- Part 2 原文链接:https://www.viget.com/articles/understanding-futur ...

  2. 闭包类型(Fn,FnMut,FnOnce)和move关键字

    move关键字是强制让环境变量的所有权转移到闭包中而不管是不是发生了所有权的转移 move关键字和匿名函数是否是FnOnce没有必然联系,之和匿名函数体有关 当匿名函数体里转移了环境变量的所有权的时候 ...

  3. JavaScript中fn()和return fn()

    看博客时,注意到return的重要性 参考:http://www.cnblogs.com/raoyunxiao/p/5644032.html 看似反常的例子: var i = 0; function ...

  4. ubuntu系统(华硕笔记本)屏幕亮度用Fn控制的调节设置

    亲测配置: 系统:Linux lite 3.2 x86_64(Ubuntu其他版本可参考修改) 笔记本:华硕(asus)1201N 达到的效果: 可以正常使用Fn+F5调暗,Fn+F6调亮. 设置步骤 ...

  5. 设置Fn键 笔记本直接按F1-F12 无须按Fn键 Fn+F12改F12(联想小新300为例)

    最近公司给配的笔记本联想小新300 80RT  i7-6500U 4G内存 500G机械,后加装120G固态+4G内存 这样就感觉还不错了. 在使用这本子的时候,去了Win10,强行装了Win7.无线 ...

  6. jquery.fn.extend与jquery.extend--(初体验二)

    1.jquery.extend(object); 为扩展jQuery类本身.为类添加新的方法. jquery.fn.extend(object);给jQuery对象添加方法. $.extend({ a ...

  7. jQuery为开发插件提拱了两个方法:jQuery.fn.extend(); jQuery.extend();

    jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(); jQuery.extend(); jQuery.fn jQuery.fn = jQuery.prototype ...

  8. Jquery揭秘系列:实现$.fn.extend 和$.extend函数

    前面我们扩展了bind方法和ready函数,这次我要讲一下$.fn.extend 和$.extend函数. 其他的不多说,直接切入主题吧! 先来看看这两个函数的区别: $.fn.extend是为查询的 ...

  9. java Fn键

    需求分析 我想开机禁用触摸板. 方案设计 安装驱动:比较麻烦,驱动也不一定支持开机禁用触摸板. 编程实现,让一段代码开机禁用触摸板 编程实现也分好几种方法: 使用windows API禁用触摸板,这需 ...

随机推荐

  1. Golang 实现 Redis(11): RDB 文件解析

    RDB 文件使用二进制方式存储 Redis 内存中的数据,具有体积小.加载快的优点.本文主要介绍 RDB 文件的结构和编码方式,并借此探讨二进制编解码和文件处理方式,希望对您有所帮助. 本文基于 RD ...

  2. 重修 Slope Trick(看这篇绝对够!)

    Slope Trick 算法存在十余载了,但是我没有找到多少拍手叫好的讲解 blog,所以凭借本人粗拙的理解来写这篇文章. 本文除标明外所有图片均为本人手绘(若丑见谅),画图真的不容易啊 qwq(无耻 ...

  3. kNN-画图

    现在我们想要展示一些可视化内容 首先导包,如果是在jupyter notebook上,需要加入魔法函数:%matplotlib inline,这表示可以在jupyter上直接画图 import dat ...

  4. Elasticsearch高级之-集群搭建,数据分片

    目录 Elasticsearch高级之-集群搭建,数据分片 一 广播方式 二 单播方式 三 选取主节点 四 什么是脑裂 五 错误识别 Elasticsearch高级之-集群搭建,数据分片 es使用两种 ...

  5. zabbix的web界面访问失败问题排查

    现象:用curl访问显示拒绝链接,查看zabbix-server日志也无异常 1.检查防火墙,SElinux是否关闭 2.检查zabbix-server服务是否启动 3.检查80端口是否被占用,比方是 ...

  6. python面向对象双下划线方法与元类

    目录 双下划线方法(__) 元类简介 产生类的两种表现形式 元类的基本使用 元类进阶操作 __new__方法 双下划线方法(__) 面向对象中的双下方法也有一些人称之为是魔法方法,有些双下方法不需要刻 ...

  7. [gym102978C] Count Min Ratio

    [gym102978C] Count Min Ratio 给定 \(B\) 个蓝色的球. \(R\) 个红色的球以及一个绿色的球,同颜色的球不可区分.对于一种球的排列方式,记 \(l_B,r_B,l_ ...

  8. 【Java面试】请说一下Mysql索引的优点和缺点?

    今天分享的这道面试题,让一个工作4年的小伙子去大众点评拿了60W年薪. 这道面试题是: "请你说一下Mysql索引的优点和缺点" 关于这道题,看看普通人和高手的回答 普通人: 嗯. ...

  9. Jmeter基础入门应用举例

    举例当然应该有接口下面以常用的百度搜索接口为例: 1.接口地址: http://www.baidu.com/s?ie=utf-8&wd=jmeter性能测试 2.请求参数 ie:编码方式,默认 ...

  10. 获取在线ip

    /** * 获取在线IP * @return String */ function getOnlineIp($format=0) { global $S_GLOBAL; if(empty($S_GLO ...