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

rust语言学习笔记(指针六)Cell<T>(内部可变(非指针))

  • 允许你在拥有不可变引用(&T)的情况下修改内部数据,从而绕过 Rust 严格的借用规则限制。
  • Rust 的默认规则是:‌要么有一个可变引用 (&mut T),要么有多个不可变引用 (&T),但不能同时存在。

6.1 关键特性

  • 单线程专用‌:Cell<T>没有实现Synctrait,因此不能在线程间安全共享。
  • 零运行时开销‌:没有锁,没有借用计数器,性能极高。
  • 仅限Copy类型‌:通常用于实现了Copytrait 的类型(如i32,u64,bool,f64等)。

6.2 常用方法

方法签名说明
newCell::new(value)创建一个新的 Cell
getcell.get() -> T复制‌出内部值(要求T: Copy
setcell.set(value)替换‌内部值为新的值
replacecell.replace(value) -> T替换内部值,并返回‌旧值
into_innercell.into_inner() -> T消耗 Cell,取出内部值的所有权
takecell.take() -> T取出内部值,并用Default::default()填充(要求T: Default

6.2 常规用法

usestd::cell::Cell;fnmain(){letdata=Cell::new(0);// 无需标记 mut 可实现可变data.set(100);// 修改值println!("{}",data.get());// 获取值}

6.3 结构体用法

usestd::cell::Cell;#[derive(Debug)]structData{value:Cell<i32>,}implData{fnnew(value:i32)->Self{Self{value:Cell::new(value),}}fnget(&self)->i32{self.value.get()// 获取值}fnset(&self,value:i32){// 无需 &mut selfself.value.set(value);// 设置值}}fnmain(){letdata=Data::new(0);data.set(100);println!("{}",data.get());}

6.4Cell<T>vsRefCell<T>

虽然两者都提供内部可变性,但适用场景截然不同。

表格

特性Cell<T>RefCell<T>
适用类型必须实现Copy(如整数、布尔、指针)任意类型 (如String,Vec, 自定义结构体)
访问方式按值拷贝‌ (get/set)按引用借用‌ (borrow/borrow_mut)
检查时机编译期‌保证安全运行时‌检查借用规则
性能开销零开销‌ (无计数器,无分支预测失败风险)有运行时开销 (维护借用计数器)
Panics?永远不会因借用规则 panic如果违反借用规则 (如同时可变和不可变借用),会 panic
典型场景简单状态、标志位、计数器复杂数据结构、树/图节点、需要引用语义的场景

选择建议:

  • 如果类型是Copy且逻辑简单,‌优先使用Cell。它更快、更安全(不会运行时崩溃)。
  • 如果类型不是Copy,或者你需要获取内部数据的引用(例如遍历一个列表),则必须使用RefCell

6.5 常见误区与注意事项

6.5.1Cell不适用于大尺寸类型

由于get()会复制整个值,如果T很大(如大型数组或结构体),get()的性能会很差。此时应考虑RefCell或其他模式。

6.5.2Cell不是智能指针

Cell<T>没有实现DerefDerefMut,因此你不能像使用BoxRc那样直接使用*cell或调用内部方法。你必须显式调用get()set()

6.5.3 线程安全

Cell<T>不是线程安全的‌。如果你需要在多线程环境中共享可变状态,应使用Mutex<T>AtomicU32等原子类型。

6.5.4 不要滥用内部可变性

内部可变性是 Rust 的“逃生舱口”。在设计 API 时,应优先遵循标准的所有权和借用规则。只有当静态借用检查器确实无法表达你的意图(如在不可变接口中更新缓存或计数)时,才使用Cell


6.6 总结

  • Cell<T>是什么?一个允许在不可变引用下修改内部值的容器。
  • 什么时候用?当你要修改的数据是Copy类型(如i32,bool),且希望避免运行时借用检查开销时。
  • 怎么用?使用set()修改值,使用get()读取值。
  • 核心优势:零运行时成本,编译期安全,代码简洁。

通过合理使用Cell<T>,你可以在保持 Rust 内存安全 guarantees 的同时,写出更灵活、更符合直觉的代码结构。

http://www.jsqmd.com/news/1108970/

相关文章:

  • shell基础知识和常用命令
  • ASM330LHH与STM32F302VC运动跟踪系统设计与优化
  • 终极指南:如何用Zotero插件市场彻底改变你的文献管理体验
  • Linuxshell编程基础课堂笔记+课后练习
  • 基于Si4731和STM32的可编程AM/FM收音机设计
  • 基于Si4732与ARM Cortex-M4的专业级收音机设计
  • DC-DC降压转换器MP8859与TM4C1299的嵌入式电源设计
  • EM3080-W与MK64FN1M0VDC12的条形码识别系统设计与优化
  • BLDC电机FOC控制:基于A89307与STM32的硬件设计与算法实现
  • 基于Si4731与TM4C129XNCZAD的收音机开发实践
  • 收藏 | AI时代工程师进化指南:5种能力取向谁更值钱?小白程序员必看!
  • 亚洲基层AI疫情预测系统落地实战:轻量模型+边缘部署+人机协同
  • 别再背稿子了!鹅来面AI面试陪练实测:STAR-C结构化表达、即时追问、5天从50分到90分
  • 终极GPU内存检测神器:5分钟掌握MemtestCL完整使用指南
  • STM32与M95M02-DR EEPROM的高效存储方案实现
  • 案例纪要:某工程设计企业图纸自动签名与批量开票RPA项目
  • STM32与Si4731的FM收音系统设计与优化
  • XZ3445输入电压2.7-36V 输出电压小于30V 5A升压/升降压型DC-DC驱动器
  • BMI270与PIC18LF47K40的低功耗嵌入式IMU开发指南
  • 3步掌握Zotero插件市场:一键安装、智能管理、高效升级
  • 【软考论文急救指南】:20年阅卷专家亲授“30分钟起稿法”与时间压缩黄金公式
  • 【Claude】上下文窗口溢出与 Token 管理优化 — 已解决
  • STM32与M95M04 EEPROM的SPI通信与数据存储实践
  • 如何快速实现Windows任务栏透明化:完整美化指南
  • 网络安全实战:5款高效漏洞挖掘工具链构建与自动化工作流指南
  • 工厂招商没素材?合肥宣传片拍摄搭配3D动画直观展示工艺
  • 如何在Windows上实现4K 240Hz高性能虚拟显示器:ParsecVDD技术深度解析
  • Yakit与流量过滤策略:精准抓取微信小程序核心API
  • 如何提升客服效率?8个技巧帮你搞定
  • 基于Si4731和STM32的FM收音系统开发指南