Rust闭包(能够捕获周围作用域变量的匿名函数,广泛应用于迭代、过滤和映射)闭包变量三种捕获方式:通过引用(不可变引用)、通过可变引用和通过值(取得所有权)

文章目录

      • Rust 闭包详解
        • 闭包的定义与语法
          • 基本语法
        • 闭包的特性
          • - 环境捕获(三种捕获方式:通过引用、通过可变引用和通过值(取得所有权))
            • 示例代码
          • - 内存安全与生命周期
            • 示例代码1
          • 示例代码2:闭包所有权转移
          • 示例代码3:传递可变引用
        • Rust 闭包的实际应用
          • - 迭代器操作
            • 示例代码
        • 总结
      • 补充:闭包变量三种捕获方式:通过引用(不可变引用)、通过可变引用和通过值(取得所有权)代码对比示例
        • 1. 通过引用捕获(不可变引用)
        • 2. 通过可变引用捕获
        • 3. 通过值捕获(取得所有权)

Rust 闭包详解

Rust 语言的闭包是一种能够捕获周围作用域变量的匿名函数。闭包在 Rust 中具有强大的表达力和灵活性,广泛应用于迭代、过滤和映射等功能。本文将深入探讨 Rust 闭包的定义、语法、特性以及实际应用示例。

闭包的定义与语法

闭包是 Rust 中一个可以捕获其环境并可以访问其作用域中变量的匿名函数。闭包通常是简短的,并且被定义在期望函数作为参数的地方。

基本语法

在 Rust 中,闭包的基本语法如下所示:

let closure_name = |parameter_list| -> return_type {// 闭包体
};

闭包的定义开始于一个竖线 |,后面跟着参数列表,参数列表的结尾也是一个竖线 |。可选的返回类型可以使用 -> 符号指定,闭包体由花括号 {} 包裹。

闭包的特性
- 环境捕获(三种捕获方式:通过引用、通过可变引用和通过值(取得所有权))

闭包可以通过三种方式捕获其环境中的变量:通过引用、通过可变引用和通过值(取得所有权)。Rust 的编译器会根据闭包体内所使用的变量的方式自动推断如何捕获这些变量。

示例代码
// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let x = 4;let equal_to_x = |z| z == x;let y = 4;assert!(equal_to_x(y));println!("y is equal to x.");
}

在这里插入图片描述

在上述示例中,闭包 equal_to_x 通过引用捕获变量 x,因为闭包内部只是将 x 与传入的参数 z 进行比较,不需要修改 x

- 内存安全与生命周期

Rust 的所有权和借用规则同样适用于闭包。这意味着闭包内的捕获变量必须保证在闭包被调用时是有效的。Rust 编译器会检查这一点,确保闭包的使用是安全的。

示例代码1
// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let mut num = 5;{let mut add_num = |x: i32| num += x;add_num(5);}assert_eq!(num, 10);println!("num is now 10.");
}

在这里插入图片描述

这里的 add_num 闭包通过可变引用捕获外部变量 num,并在闭包体内修改 num 的值。

示例代码2:闭包所有权转移
// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let s = String::from("Hello");let push_string = |mut s_: String| s_.push_str(", world");push_string(s);// assert_eq!(s, String::from("Hello, world")); // 报错// println!("s is now \"Hello, world\".");
}
示例代码3:传递可变引用
// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let mut s = String::from("Hello");let push_string = |s_: &mut String| s_.push_str(", world");push_string(&mut s);assert_eq!(s, String::from("Hello, world"));println!("s is now \"Hello, world\".");
}

在这里插入图片描述

Rust 闭包的实际应用
- 迭代器操作

Rust 中的迭代器广泛使用闭包,尤其是在 mapfilterfold 等方法中。

示例代码
// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let numbers = vec![1, 2, 3, 4, 5];let squared_numbers: Vec<i32> = numbers.iter().map(|&x| x * x).collect();println!("Squared numbers: {:?}", squared_numbers); // 输出: [1, 4, 9, 16, 25]let even_numbers: Vec<i32> = numbers.into_iter().filter(|x| x % 2 == 0).collect();println!("Even numbers: {:?}", even_numbers); // 输出: [2, 4]
}

在这里插入图片描述

这个示例展示了如何使用闭包在迭代器上执行映射和过滤操作,map 用于计算平方,filter 用于选择偶数。

总结

Rust 的闭包提供了一个强大且灵活的工具,能够在许多不同的情境下灵活处理数据。通过闭包,Rust 程序员可以编写出既安全又高效的代码。

补充:闭包变量三种捕获方式:通过引用(不可变引用)、通过可变引用和通过值(取得所有权)代码对比示例

当然可以。以下是三个独立的代码块,每个代码块展示了 Rust 闭包中一种特定的变量捕获方式:通过引用、通过可变引用、和通过值(取得所有权)。每个示例都会通过闭包的参数来展示具体的捕获操作。

1. 通过引用捕获(不可变引用)

这个示例演示了闭包如何通过不可变引用捕获外部环境中的变量。

// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let color = String::from("blue");// 通过不可变引用捕获 colorlet print_color = |color_ref: &String| println!("Color: {}", color_ref);print_color(&color);
}

在这里插入图片描述

这里,print_color 是一个接收一个 &String 类型参数的闭包,它通过不可变引用来访问外部定义的 color 变量。

2. 通过可变引用捕获

这个示例展示了闭包如何通过可变引用捕获并修改外部环境中的变量。

// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let mut count = 0;// 通过可变引用捕获 countlet increment_count = |count_ref: &mut i32| {*count_ref += 1;println!("Count: {}", *count_ref);// println!("Count: {}", count_ref); // 都可以,自动判断的};increment_count(&mut count);increment_count(&mut count);
}

在这里插入图片描述

在这个示例中,increment_count 是一个接收 &mut i32 类型参数的闭包,它通过可变引用来修改传入的 count 变量。

3. 通过值捕获(取得所有权)

这个示例演示了闭包如何通过值捕获(取得所有权)外部环境中的变量。

// 测试代码
#![allow(dead_code)] // 忽略全局dead code,放在模块开头!// #[derive(Debug)]fn main() {let color = String::from("blue");// 通过值捕获 colorlet consume_color = |color_val: String| println!("Moved Color: {}", color_val);consume_color(color);// 注意:在这里调用 consume_color 后,color 不再有效// 下面的代码如果取消注释,将会引起编译错误,因为 color 的所有权已经移至闭包中// println!("Try to access color: {}", color);
}

在这里插入图片描述

在这个示例中,consume_color 是一个接收 String 类型参数的闭包,它通过值捕获来获取 color 的所有权。一旦闭包被调用,原始的 color 变量就不再可用了。


这些代码块展示了如何明确通过闭包参数直接传递外部变量,并通过不同的捕获机制来处理这些变量。这种方式需要闭包调用者明确知道闭包的捕获机制和参数类型。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.xdnf.cn/news/3935.html

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【xxl-job总结】

文章目录 xxl-job介绍系统组成为什么不使用quartz过期处理策略避免任务重复执行源码分析 xxl-job介绍 XXL-JOB是一个轻量级分布式任务调度平台&#xff0c;它的核心设计目标是开发迅速、学习简单、轻量级、易扩展。 1.简单易用&#xff1a;XXL-JOB提供了友好的Web界面&#xf…

19. 架构重要需求

文章目录 第19章 架构重要需求19.1 从需求文档中收集架构重要需求&#xff08;ASRs&#xff09;不要抱太大希望从需求文档中找出架构重要需求 19.2 通过访谈利益相关者收集架构重要需求19.3 通过理解业务目标收集架构重要需求19.4 在效用树中捕获架构重要需求19.5 变化总会发生…

简易CPU设计入门:译码模块(一)

项目代码下载 还是请大家首先准备好本项目所用的源代码。如果已经下载了&#xff0c;那就不用重复下载了。如果还没有下载&#xff0c;那么&#xff0c;请大家点击下方链接&#xff0c;来了解下载本项目的CPU源代码的方法。 下载本项目代码 准备好了项目源代码以后&#xff…

Hunyuan-Large:腾讯发布业界参数规模最大的开源 MoE 模型,支持超长文本输入,超越主流开源模型

❤️ 如果你也关注大模型与 AI 的发展现状&#xff0c;且对大模型应用开发非常感兴趣&#xff0c;我会快速跟你分享最新的感兴趣的 AI 应用和热点信息&#xff0c;也会不定期分享自己的想法和开源实例&#xff0c;欢迎关注我哦&#xff01; &#x1f966; 微信公众号&#xff…

Linux基础

1. openssl passwd -1 密码 128位 openssl passwd -5 密码&#xff08;更安全&#xff09;256位 openssl是开源的加密工具包&#xff0c;有各种加密&#xff0c;解密等功能 2. 文件管理 创建空文件 touch newfile 删除文件 rm new file 新建日录 mkdir newdir 删除…

HuggingFace情感分析任务微调

官方教程地址&#xff1a;https://huggingface.co/learn/nlp-course/zh-CN/chapter3/1?fwpt 部分内容参考&#xff1a; 李福林, & 计算机技术. (2023). HuggingFace 自然语言处理详解: 基于 BERT 中文模型的任务实战. 清华大学出版社. HuggingFace将AI项目研发分为四个步骤…

Springboot——对接支付宝实现扫码支付

文章目录 前言官方文档以及说明1、申请沙箱2、进入沙箱获取对应的关键信息3、拿到系统生成的公钥和密钥 注意事项创建springboot项目1、引入依赖2、配置连接参数3、创建配置类&#xff0c;用于接收这些参数4、中间类的定义(订单类)5、编写测试接口场景一、pc端请求后端后&#…

迪杰斯特拉算法

迪杰斯特拉算法 LeetCode 743. 网络延迟时间 https://blog.csdn.net/xiaoxi_hahaha/article/details/110257368 import sysdef dijkstra(graph, source):"""dijkstra算法:param graph: 邻接矩阵:param source: 出发点&#xff0c;源点:return:""&…

STL学习-容器适配器

一.stack栈 1.栈的介绍 stack 栈是一种只在一端(栈顶)进行数据插入(入栈)和删除(出栈)的数据结构,它满足后进 先出(LIFO)的特性。 使用push(入栈)将数据放入stack,使用pop(出栈)将元素从容器中移除。 栈的结构如图&#xff1a; 在头文件<stack>中&#xff0c;class st…

【C语言】动态内存开辟

写在前面 C语言中有不少开辟空间的办法&#xff0c;但是在堆上开辟的方法也就只有动态内存开辟&#xff0c;其访问特性与数组相似&#xff0c;但最大区别是数组是开辟在栈上&#xff0c;而动态内存开辟是开辟在堆上的。这篇笔记就让不才娓娓道来。 PS:本篇没有目录实在抱歉CSD…

海的记忆:海滨学院班级回忆录项目

4系统概要设计 4.1概述 本系统采用B/S结构(Browser/Server,浏览器/服务器结构)和基于Web服务两种模式&#xff0c;是一个适用于Internet环境下的模型结构。只要用户能连上Internet,便可以在任何时间、任何地点使用。系统工作原理图如图4-1所示&#xff1a; 图4-1系统工作原理…

【VScode】C/C++多文件夹下、多文件引用、分别编译——仅一个设置【适合新人入手】

【VScode】C/C多文件夹内的多文件引用编译 1、问题2、前提&#xff08;最简环境&#xff09;3、核心&#xff08;关键配置&#xff09;4、成功享用~ 1、问题 在使用 VScode 编写一个简单项目的时候&#xff0c;没有特别配置的情况下&#xff0c;若主文件(.c)引用了自定义的头文…

62 mysql 中 存储引擎MyISAM 中索引的使用

前言 固定数据表 mysql. tables_priv 的表结构创建如下 CREATE TABLE tables_priv (Host char(60) COLLATE utf8_bin NOT NULL DEFAULT ,Db char(64) COLLATE utf8_bin NOT NULL DEFAULT ,User char(32) COLLATE utf8_bin NOT NULL DEFAULT ,Table_name char(64) COLLATE u…

使用buildx构建多架构平台镜像

1. 查看buildx插件信息 比较新的docker-ce版本默认已经集成了buildx插件 [rootdocker ~]# docker buildx version github.com/docker/buildx v0.11.2 9872040 [rootdocker ~]#2. 增加多平台镜像构建支持 通过tonistiigi/binfmt:latest初始化一个基于容器的构建环境&#xff…

数据库基础(3) . Navicat使用

0.下载安装 官网 : https://www.navicat.com.cn/ Navicat 中国 | 支持 MySQL、Redis、MariaDB、MongoDB、SQL Server、SQLite、Oracle 和 PostgreSQL 的数据库管理 1.连接数据库 1.1.连接 1.1.1.点击连接 打开navicat 点击 左上角连接 1.1.2.选择MySQL 弹出配置界面 1.1…

MySQL(上)

一、SQL优化 1、如何定位及优化SQL语句的性能问题&#xff1f;创建的索引有没有被使用到?或者说怎么才可以知道这条语句运行很慢的原因&#xff1f; 对于性能比较低的sql语句定位&#xff0c;最重要的也是最有效的方法其实还是看sql的执行计划&#xff0c;而对于mysql来说&a…

国密SM2 非对称加解密前后端工具

1.依赖 <dependency><groupId>cn.hutool</groupId><artifactId>hutool-all</artifactId><version>5.8.21</version></dependency><dependency><groupId>org.bouncycastle</groupId><artifactId>bcpki…

【银河麒麟操作系统】软raid重建速度限制问题分析

了解更多银河麒麟操作系统全新产品&#xff0c;请点击访问 麒麟软件产品专区&#xff1a;https://product.kylinos.cn 开发者专区&#xff1a;https://developer.kylinos.cn 文档中心&#xff1a;https://documentkylinos.cn 现象描述 遇到软raid重建速度问题&#xff0c;分…

ssm教室信息管理系统+vue

系统包含&#xff1a;源码论文 所用技术&#xff1a;SpringBootVueSSMMybatisMysql 免费提供给大家参考或者学习&#xff0c;获取源码看文章最下面 需要定制看文章最下面 目 录 目 录 III 1 绪论 1 1.1 研究背景 1 1.2目的和意义 1 1.3 论文结构安排 2 2 相关技术 3 …

去中心化存储:Web3中的数据安全新标准

随着Web3的兴起&#xff0c;去中心化存储逐渐成为数据安全的新标准。传统的中心化存储方式将数据集中保存在少数服务器上&#xff0c;这种模式尽管在早期互联网中被广泛应用&#xff0c;但随着数据量和数据价值的增加&#xff0c;其潜在的安全风险和隐私问题也逐渐暴露。而去中…