元素码农
基础
UML建模
数据结构
算法
设计模式
网络
TCP/IP协议
HTTPS安全机制
WebSocket实时通信
数据库
sqlite
postgresql
clickhouse
后端
rust
go
java
php
mysql
redis
mongodb
etcd
nats
zincsearch
前端
浏览器
javascript
typescript
vue3
react
游戏
unity
unreal
C++
C#
Lua
App
android
ios
flutter
react-native
安全
Web安全
测试
软件测试
自动化测试 - Playwright
人工智能
Python
langChain
langGraph
运维
linux
docker
工具
git
svn
🌞
🌙
目录
▶
所有权系统
所有权规则
借用与引用
Move语义
切片与所有权
▶
生命周期
生命周期基础
生命周期省略规则
结构体中的生命周期
高阶生命周期
▶
类型系统
Traits与泛型
类型推断机制
PhantomData与泛型约束
Newtype模式
▶
并发模型
线程与消息传递
共享状态并发
异步编程基础
Future与Executor
▶
内存管理
栈与堆内存布局
内存分配器原理
Box与智能指针
内存安全策略
▶
错误处理
Result与Option
错误传播机制
Panic与Abort
自定义错误类型
▶
宏系统
声明宏与过程宏
宏展开机制
卫生宏实现
元编程实践
▶
Unsafe Rust
Unsafe关键字解析
原始指针操作
FFI交互实践
安全抽象模式
发布时间:
2025-03-22 08:54
↑
☰
# Box与智能指针 Rust的智能指针是一类数据结构,它们不仅具有指针的功能,还具有额外的元数据和功能。本文将详细介绍Rust中的各种智能指针及其应用。 ## Box智能指针 ### 1. 基本用法 ```rust fn main() { // 在堆上分配值 let b = Box::new(5); println!("b = {}", b); // 递归类型定义 #[derive(Debug)] enum List { Cons(i32, Box<List>), Nil, } let list = List::Cons(1, Box::new(List::Cons(2, Box::new(List::Cons(3, Box::new(List::Nil)))))); println!("list = {:?}", list); } ``` ### 2. 大型数据堆分配 ```rust fn main() { // 在栈上可能过大的数组 let large_array = Box::new([0; 1000000]); // 使用数组而不会导致栈溢出 println!("数组长度: {}", large_array.len()); } ``` ## Rc引用计数智能指针 ### 1. 基本概念 ```rust use std::rc::Rc; fn main() { let data = Rc::new(String::from("Hello")); let data1 = Rc::clone(&data); let data2 = Rc::clone(&data); println!("引用计数: {}", Rc::strong_count(&data)); println!("数据: {} {} {}", data, data1, data2); } ``` ### 2. 共享所有权 ```rust use std::rc::Rc; #[derive(Debug)] struct Node { value: i32, next: Option<Rc<Node>>, } fn main() { let node3 = Rc::new(Node { value: 3, next: None, }); let node2 = Rc::new(Node { value: 2, next: Some(Rc::clone(&node3)), }); let node1 = Node { value: 1, next: Some(Rc::clone(&node2)), }; println!("node1: {:?}", node1); } ``` ## RefCell内部可变性 ### 1. 基本用法 ```rust use std::cell::RefCell; fn main() { let data = RefCell::new(5); // 可变借用 *data.borrow_mut() += 1; // 不可变借用 println!("data = {}", data.borrow()); } ``` ### 2. 与Rc结合使用 ```rust use std::rc::Rc; use std::cell::RefCell; #[derive(Debug)] struct Node { value: i32, children: RefCell<Vec<Rc<Node>>>, } fn main() { let node = Rc::new(Node { value: 1, children: RefCell::new(vec![]), }); let child = Rc::new(Node { value: 2, children: RefCell::new(vec![]), }); // 可以修改不可变引用中的值 node.children.borrow_mut().push(Rc::clone(&child)); println!("节点: {:?}", node); } ``` ## Weak弱引用 ### 1. 避免循环引用 ```rust use std::rc::{Rc, Weak}; use std::cell::RefCell; #[derive(Debug)] struct Node { value: i32, parent: RefCell<Weak<Node>>, children: RefCell<Vec<Rc<Node>>>, } fn main() { let parent = Rc::new(Node { value: 1, parent: RefCell::new(Weak::new()), children: RefCell::new(vec![]), }); let child = Rc::new(Node { value: 2, parent: RefCell::new(Rc::downgrade(&parent)), children: RefCell::new(vec![]), }); parent.children.borrow_mut().push(Rc::clone(&child)); // 打印树结构 if let Some(parent) = child.parent.borrow().upgrade() { println!("子节点的父节点值: {}", parent.value); } } ``` ### 2. 缓存和记忆化 ```rust use std::rc::{Rc, Weak}; use std::cell::RefCell; use std::collections::HashMap; struct Cache { map: RefCell<HashMap<String, Weak<String>>>, } impl Cache { fn new() -> Self { Cache { map: RefCell::new(HashMap::new()), } } fn get_or_insert(&self, key: &str) -> Rc<String> { if let Some(value) = self.map.borrow().get(key) { if let Some(string) = value.upgrade() { return string; } } let value = Rc::new(String::from(key)); self.map.borrow_mut().insert( key.to_string(), Rc::downgrade(&value) ); value } } ``` ## 自定义智能指针 ### 1. 实现Deref特征 ```rust use std::ops::Deref; struct MyBox<T>(T); impl<T> MyBox<T> { fn new(x: T) -> MyBox<T> { MyBox(x) } } impl<T> Deref for MyBox<T> { type Target = T; fn deref(&self) -> &Self::Target { &self.0 } } fn main() { let x = MyBox::new(5); assert_eq!(5, *x); } ``` ### 2. 实现Drop特征 ```rust struct CustomSmartPointer { data: String, } impl Drop for CustomSmartPointer { fn drop(&mut self) { println!("正在删除 CustomSmartPointer,数据: {}", self.data); } } fn main() { let c = CustomSmartPointer { data: String::from("我的数据"), }; println!("CustomSmartPointer 已创建"); // c在这里被自动删除 } ``` ## 最佳实践 ### 1. 选择合适的智能指针 ```rust use std::rc::Rc; use std::cell::RefCell; // 单一所有权,需要在堆上分配 fn use_box() { let data = Box::new(42); println!("Box: {}", data); } // 多重所有权 fn use_rc() { let data = Rc::new(42); let data2 = Rc::clone(&data); println!("Rc: {} {}", data, data2); } // 内部可变性 fn use_refcell() { let data = RefCell::new(42); *data.borrow_mut() += 1; println!("RefCell: {}", data.borrow()); } // 组合使用 fn use_combined() { let data = Rc::new(RefCell::new(42)); let data2 = Rc::clone(&data); *data2.borrow_mut() += 1; println!("Combined: {}", data.borrow()); } ``` ### 2. 性能考虑 ```rust use std::rc::Rc; use std::cell::RefCell; fn main() { // Box性能最好,开销最小 let box_data = Box::new(42); // Rc有引用计数开销 let rc_data = Rc::new(42); // RefCell有运行时检查开销 let refcell_data = RefCell::new(42); // 根据需求选择合适的智能指针 println!("Box: {}", box_data); println!("Rc count: {}", Rc::strong_count(&rc_data)); println!("RefCell: {}", refcell_data.borrow()); } ``` ## 注意事项 1. **内存管理**: - 及时释放不再需要的引用 - 避免循环引用 - 合理使用弱引用 2. **性能优化**: - 优先使用Box - 避免过度使用RefCell - 注意Rc的引用计数开销 3. **安全性**: - 正确处理借用规则 - 避免RefCell的运行时panic - 谨慎使用内部可变性 ## 总结 Rust的智能指针系统提供了强大而灵活的内存管理能力。通过合理使用各种智能指针,我们可以: 1. 实现复杂的数据结构 2. 管理共享所有权 3. 实现内部可变性 在实际开发中,应根据具体需求选择合适的智能指针类型,并始终注意内存安全和性能的平衡。