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

借用与引用实战

Rust 借用与引用实战

引言

借用是 Rust 中使用值而不获取其所有权的方式。通过引用,我们可以在不转移所有权的情况下访问数据。Rust 的借用检查器确保引用始终有效。

借用规则

借用遵循两条关键规则:

  1. 在任意给定时间,要么只能有一个可变引用,要么只能有多个不可变引用
  2. 引用必须总是有效的

基础示例

fn main() {let mut s = String::from("hello");// 不可变借用let r1 = &s;let r2 = &s;println!("{} and {}", r1, r2);// 可变借用let r3 = &mut s;r3.push_str(", world");println!("{}", r3);
}

复杂案例:实现一个缓存系统

下面实现一个支持并发访问的缓存系统,展示借用在实际场景中的应用。

use std::collections::HashMap;
use std::hash::Hash;struct Cache<K, V> 
where K: Eq + Hash + Clone,V: Clone,
{store: HashMap<K, V>,max_size: usize,access_count: HashMap<K, usize>,
}impl<K, V> Cache<K, V> 
whereK: Eq + Hash + Clone,V: Clone,
{fn new(max_size: usize) -> Self {Cache {store: HashMap::new(),max_size,access_count: HashMap::new(),}}// 不可变借用:读取缓存fn get(&mut self, key: &K) -> Option<&V> {if let Some(count) = self.access_count.get_mut(key) {*count += 1;}self.store.get(key)}// 可变借用:插入或更新缓存fn insert(&mut self, key: K, value: V) {if self.store.len() >= self.max_size && !self.store.contains_key(&key) {self.evict_least_used();}self.store.insert(key.clone(), value);self.access_count.insert(key, 1);}// 淘汰最少使用的项fn evict_least_used(&mut self) {if let Some((&ref key, _)) = self.access_count.iter().min_by_key(|(_, &count)| count) {let key_to_remove = key.clone();self.store.remove(&key_to_remove);self.access_count.remove(&key_to_remove);}}// 不可变借用:获取统计信息fn stats(&self) -> CacheStats {let total_accesses: usize = self.access_count.values().sum();CacheStats {size: self.store.len(),max_size: self.max_size,total_accesses,}}// 不可变借用:检查是否包含键fn contains(&self, key: &K) -> bool {self.store.contains_key(key)}// 可变借用:清空缓存fn clear(&mut self) {self.store.clear();self.access_count.clear();}
}struct CacheStats {size: usize,max_size: usize,total_accesses: usize,
}impl CacheStats {fn print(&self) {println!("缓存统计:");println!("  当前大小: {}/{}", self.size, self.max_size);println!("  总访问次数: {}", self.total_accesses);println!("  使用率: {:.2}%", (self.size as f64 / self.max_size as f64) * 100.0);}
}fn demonstrate_cache() {let mut cache = Cache::new(3);// 插入数据cache.insert("user:1", "Alice");cache.insert("user:2", "Bob");cache.insert("user:3", "Charlie");// 读取数据(不可变借用)if let Some(user) = cache.get(&"user:1") {println!("找到用户: {}", user);}// 再次访问增加计数cache.get(&"user:1");cache.get(&"user:2");// 插入新数据,触发淘汰cache.insert("user:4", "David");// 检查缓存内容println!("user:3 还在缓存中吗? {}", cache.contains(&"user:3"));// 打印统计信息cache.stats().print();
}// 演示引用的生命周期
fn reference_lifetime_demo() {let data = vec![1, 2, 3, 4, 5];// 借用切片let slice = &data[1..4];println!("切片内容: {:?}", slice);// 同时存在多个不可变引用let ref1 = &data;let ref2 = &data;let ref3 = &data;println!("Sum via ref1: {}", ref1.iter().sum::<i32>());println!("Len via ref2: {}", ref2.len());println!("First via ref3: {}", ref3[0]);
}// 实现一个需要精确控制借用的数据结构
struct BorrowTracker<T> {data: T,borrow_count: usize,mut_borrowed: bool,
}impl<T> BorrowTracker<T> {fn new(data: T) -> Self {BorrowTracker {data,borrow_count: 0,mut_borrowed: false,}}fn borrow(&mut self) -> Result<&T, String> {if self.mut_borrowed {return Err("数据已被可变借用".to_string());}self.borrow_count += 1;Ok(&self.data)}fn borrow_mut(&mut self) -> Result<&mut T, String> {if self.borrow_count > 0 {return Err(format!("数据已被借用 {} 次", self.borrow_count));}if self.mut_borrowed {return Err("数据已被可变借用".to_string());}self.mut_borrowed = true;Ok(&mut self.data)}fn release(&mut self) {if self.borrow_count > 0 {self.borrow_count -= 1;}}fn release_mut(&mut self) {self.mut_borrowed = false;}
}fn demonstrate_borrow_tracking() {let mut tracker = BorrowTracker::new(vec![1, 2, 3]);// 不可变借用match tracker.borrow() {Ok(data) => println!("借用成功: {:?}", data),Err(e) => println!("借用失败: {}", e),}tracker.release();// 可变借用match tracker.borrow_mut() {Ok(data) => {data.push(4);println!("可变借用成功,修改后: {:?}", data);},Err(e) => println!("可变借用失败: {}", e),}tracker.release_mut();
}fn main() {demonstrate_cache();println!("\n---\n");reference_lifetime_demo();println!("\n---\n");demonstrate_borrow_tracking();
}

借用与迭代器

迭代器是借用的典型应用场景:

fn iterator_borrowing() {let numbers = vec![1, 2, 3, 4, 5];// iter() 创建不可变引用的迭代器let sum: i32 = numbers.iter().sum();println!("和: {}", sum);// 原始数据仍然可用println!("原始数据: {:?}", numbers);// 过滤和映射let even_squares: Vec<i32> = numbers.iter().filter(|&&x| x % 2 == 0).map(|&x| x * x).collect();println!("偶数的平方: {:?}", even_squares);
}

总结

借用和引用是 Rust 实现内存安全的关键机制。通过编译时检查,Rust 确保引用的正确使用,避免数据竞争和悬垂引用。

http://www.dtcms.com/a/536592.html

相关文章:

  • 涉密资质 网站建设整站seo策略实施
  • 【数据结构】链表补充——静态链表、循环链表、双向链表与双向循环链表
  • Python测试题1
  • 解锁仓颉语言:探索全场景智能编程新范式
  • 大模型-模型压缩:量化、剪枝、蒸馏、二值化 (3)
  • C++进阶:(二)多态的深度解析
  • 天汇大厦网站建设公司佳木斯做网站公司
  • Java 大视界 -- 基于 Java 的大数据可视化在城市交通拥堵溯源与治理策略展示中的应用
  • 从零实现一个完整的vector类:深入理解C++动态数组
  • JVM从操作系统层面的总体启动流程
  • C++list类的模拟实现
  • 深圳三站合一网站建设网站建设推广怎样找客户
  • 【多所高校主办】第七届机器人、智能控制与人工智能国际学术会议(RICAI 2025)
  • 做网站有虚拟服务器什么是网络营销产生的基础
  • 高配款浮标五参数—可以及时掌握水体的生态状况
  • 《Java 实用技巧:均匀取元素算法(支持不足补齐)》
  • 【Linux】nohup命令
  • 泰州网站建设案例昆明网站seo外包
  • 【成长纪实】星光不负 码向未来|我的 HarmonyOS 学习之路与社区成长故事
  • 网站服务器租用4t多少钱一年啊提供网站建设公司有哪些
  • 如何处理系统环境变量的字符长度超过了 Windows 对话框的限制(2047 个字符)
  • 快速上手大模型:深度学习1(初识、神经网络基础)
  • Java---StringBuffer类
  • 【从零开始构建性能测试体系-10】人工智能与性能测试:如何借助AI提升测试效率
  • 网站建设人员要与客户谈什么一篇关于大学网站建设与管理的论文
  • 子洲网站建设制作网站上做网页怎么改图片
  • kafka使用-Producer
  • CUDA实现的点云MLS滤波
  • Spring Framework源码解析——TaskScheduler
  • 【从零开始开发远程桌面连接控制工具】02-服务端实现详解