继承结构

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. ajax、axios、fetch

    XMLHttpRequest: XHR中文解释为: 可扩展超文本传输请求:XML可扩展标记语言,Http超文本传输协议,Request请求: XHR对象用于与服务器交换数据,所有现代游览器都支持XHR ...

  2. 万字长文详解HBase读写性能优化

    一.HBase 读优化 1. HBase客户端优化 和大多数系统一样,客户端作为业务读写的入口,姿势使用不正确通常会导致本业务读延迟较高实际上存在一些使用姿势的推荐用法,这里一般需要关注四个问题: 1 ...

  3. logging、openpyxl、第三方模块下载

    ### 日志模块的组成部分 ```pythonimport logging# 1.logger对象:产生日志logger = logging.getLogger('转账记录')# 2.filter对象 ...

  4. postman 脚本和变量

    背景 后端接口有登录或鉴权验证,通过 swagger 调用比较费劲,并且 java 的 swagger 库(不够自动化,嵌套类支持需要各种配置才能正常显示 schema)个人感觉也没有 .net co ...

  5. Hbase——API操作

    1.判断表是否存在 public static boolean isTableExit(String tableName) throws IOException { // //获取配置文件信息 // ...

  6. Zookeeper安装学习(二)

    学习内容:Zookeeper集群安装(Zookeeper版本:Zookeeper3.5.7:注:master,s1,s2都需要部署) 解压安装: (1)在主机 master 解压 Zookeeper ...

  7. transforms.py

    from PIL import Image from torchvision import transforms #python的用法-->tensor数据类型 #通过transforms.To ...

  8. GDKOI 2021 Day1 PJ 爆炸记

    早上睡到 7:10 分才想起今天有 GDKOI ,赶紧去买了一个面包赶去机房 发现隔壁的大奆都过来了.比赛时由于昨晚一直没睡好,打了两个小时的哈欠 T1 :暴力模拟 根据 \(r\) 和 \(c\) ...

  9. Ubuntu远程桌面助手(URDC)

    目前自动驾驶域控制器项目中使用了英伟达的Orin芯片+Ubuntu20.04系统.域控属于典型的Headless设备,开发调试时需要连接显示器(HDMI/DP).鼠标和键盘,或者使用NoMachine ...

  10. 获取mybatis注解方式新增数据时非自增插入的主键

    场景:插入数据的时候,获取不到非自增的主键.原因:对象中没有主键的值,插入后主键才有值. 解决方案:使用 @SelectKey @SelectKey中: statement是要运行的SQL语句,即查询 ...