当前位置: 首页 > news >正文

Rust 闭包

        在 Rust 中,闭包(closures)是强大的匿名函数,可以捕获其环境中的变量。以下是 Rust 闭包的全面解析:

一、基础闭包语法

// 无参数闭包
let greet = || println!("Hello!");
greet();// 带参数闭包
let add = |a: i32, b: i32| -> i32 { a + b };
println!("Sum: {}", add(3, 5));// 类型可省略(编译器推断)
let multiply = |x, y| x * y;
println!("Product: {}", multiply(4, 6));

二、捕获环境变量(核心特性)

1. 不可变借用(Fn trait)
let msg = "Hello".to_string();
let print_msg = || println!("{}", msg); // 捕获不可变引用
print_msg();
println!("Original: {}", msg); // 仍可访问
2. 可变借用(FnMut trait)
let mut count = 0;
let mut increment = || {count += 1; // 捕获可变引用println!("Count: {}", count);
};
increment();
increment();
3. 获取所有权(FnOnce trait)
let data = vec![1, 2, 3];
let consume_data = move || { // `move` 关键字强制获取所有权println!("Data: {:?}", data);// data 所有权被移动到闭包内
};
consume_data();
// println!("{:?}", data); // 错误!data 所有权已转移

三、闭包类型系统

特征 (Trait)捕获方式调用方法可调用次数
Fn不可变引用call()多次
FnMut可变引用call_mut()多次
FnOnce获取所有权call_once()仅一次

四、闭包作为函数参数

// 使用泛型和 trait 约束
fn apply_twice<F>(mut f: F, x: i32) -> i32
whereF: FnMut(i32) -> i32,
{f(f(x))
}let result = apply_twice(|x| x * 2, 5);
println!("Result: {}", result); // 20

五、闭包作为返回值

// 返回装箱闭包
fn make_adder(x: i32) -> Box<dyn Fn(i32) -> i32> {Box::new(move |y| x + y)
}let add_five = make_adder(5);
println!("10 + 5 = {}", add_five(10));// 使用 impl Trait(更高效)
fn multiplier(factor: i32) -> impl Fn(i32) -> i32 {move |x| x * factor
}
let triple = multiplier(3);
println!("7 * 3 = {}", triple(7));

六、闭包与迭代器(黄金组合)

let numbers = vec![1, 2, 3, 4, 5];// 过滤偶数
let evens: Vec<_> = numbers.iter().filter(|&x| x % 2 == 0).collect();// 平方和
let sum_of_squares: i32 = numbers.iter().map(|x| x * x).sum();

七、高级用法

1. 环境变量选择性捕获
let (a, mut b) = (10, 20);
let closure = || {println!("a: {}", a);  // 不可变借用 ab += 1;               // 可变借用 b
};
closure();
2. 结构体中存储闭包
struct Cache<T>
whereT: Fn(i32) -> i32,
{calculation: T,value: Option<i32>,
}let expensive_closure = |x| {// 模拟复杂计算x * x
};
let mut c = Cache {calculation: expensive_closure,value: None,
};
3. 多线程中的闭包
use std::thread;let value = 42;
let handle = thread::spawn(move || {println!("Value in thread: {}", value);
});
handle.join().unwrap();

八、性能特点

  1. 零成本抽象:闭包在运行时通常被优化为普通函数

  2. 内联优化:小闭包常被编译器内联

  3. 无堆分配:不捕获环境的闭包无需堆分配

  4. 类型大小:捕获的变量决定闭包大小

九、闭包 vs 函数指针

特性闭包函数指针 (fn)
捕获环境支持不支持
大小取决于捕获内容固定大小(指针)
性能通常更高间接调用开销
使用场景需要上下文时C 交互/无状态操作

十、最佳实践

  1. 优先使用不可变借用(Fn

  2. 需要修改环境时用 FnMut

  3. 跨线程传递数据用 move + FnOnce

  4. 简单逻辑直接用闭包而非定义函数

  5. 复杂逻辑考虑重构为命名函数

// 实用示例:自定义排序
let mut words = ["apple", "banana", "cherry"];
words.sort_by(|a, b| a.len().cmp(&b.len()));
println!("Sorted: {:?}", words); // ["apple", "cherry", "banana"]

        闭包是 Rust 函数式编程的核心,合理使用可使代码更简洁高效,同时保持内存安全性。

http://www.lryc.cn/news/579965.html

相关文章:

  • 暴雨服务器成功中标华中科技大学集成电路学院服务器采购项目
  • 封装一个png的编码解码操作
  • 数据库位函数:原理、应用与性能优化
  • 企业该怎么做竞争分析?一文了解
  • Linux-进程概念(3)
  • 【WEB】Polar靶场 6-10题 详细笔记
  • 类图+案例+代码详解:软件设计模式----原型模式
  • vue3 el-table 行筛选 设置为单选
  • 电商分拣的“效率密码”:艾立泰轻量化托盘引领自动化流水线革新
  • vue3 获取选中的el-table行数据
  • 【WRFDA第三期】OBSPROC namelist 变量总结
  • Ubuntu 22.04 + MySQL 8 无密码登录问题与 root 密码重置指南
  • OpenCV中DPM(Deformable Part Model)目标检测类cv::dpm::DPMDetector
  • 前端基础知识Webpack系列 - 03(webpack中常见的Loader?解决了什么问题?)
  • STM32CubeMX教程1 实现点灯点灯
  • 量化开发(系列第3篇): C++在高性能量化交易中的核心应用与技术栈深度解析
  • 三态逻辑详解:单片机GPIO、计算机总线系统举例
  • 【python实用小脚本-128】基于 Python 的 Hacker News 爬虫工具:自动化抓取新闻数据
  • RK-Android11-性能优化-限制App内存上限默认512m
  • 基于Hadoop的公共自行车数据分布式存储和计算平台的设计与实现
  • 如何调节笔记本电脑亮度?其实有很多种方式可以调整亮度
  • Mysql+neo4j创建节点和关系
  • [环境安装] 图数据库Neo4j 2025.05 安装(apple M芯片)
  • XILINX Kintex 7系列FPGA的全局时钟缓冲器(BUFG)和区域时钟缓冲器(BUFR/BUFH)的区别
  • EPLAN 电气制图:建立自己的部件库,添加部件-加SQL Server安装教程(三)上
  • HarmonyOS学习记录3
  • 2025微信小程序wxapkg解包全攻略
  • 怎么下载Eclipse CDT历史版本
  • 深度剖析:如何解决Node.js中mysqld_stmt_execute参数错误
  • 【Maven】Maven命令大全手册:28个核心指令使用场景