智能指针完全指南
Rust 智能指针完全指南
简介
智能指针是一类数据结构,它们的行为类似于指针,但拥有额外的元数据和功能。Rust 标准库提供了多种智能指针,用于不同的场景。
主要智能指针类型
Box<T>- 堆上分配Rc<T>- 引用计数Arc<T>- 原子引用计数RefCell<T>- 内部可变性Mutex<T>- 互斥锁
Box - 堆分配
Box 是最简单的智能指针,用于在堆上分配值。
fn box_examples() {// 基本用法let b = Box::new(5);println!("b = {}", b);// 递归类型必须使用 Box#[derive(Debug)]enum List {Cons(i32, Box<List>),Nil,}use List::{Cons, Nil};let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));println!("列表: {:?}", list);
}
复杂案例:实现一个二叉搜索树
使用 Box 实现一个功能完整的二叉搜索树:
use std::cmp::Ordering;#[derive(Debug)]
struct TreeNode<T> {value: T,left: Option<Box<TreeNode<T>>>,right: Option<Box<TreeNode<T>>>,
}struct BinarySearchTree<T> {root: Option<Box<TreeNode<T>>>,size: usize,
}impl<T: Ord + std::fmt::Debug> BinarySearchTree<T> {fn new() -> Self {BinarySearchTree {root: None,size: 0,}}fn insert(&mut self, value: T) {self.size += 1;self.root = Self::insert_node(self.root.take(), value);}fn insert_node(node: Option<Box<TreeNode<T>>>, value: T) -> Option<Box<TreeNode<T>>> {match node {None => Some(Box::new(TreeNode {value,left: None,right: None,})),Some(mut n) => {match value.cmp(&n.value) {Ordering::Less => {n.left = Self::insert_node(n.left.take(), value);}Ordering::Greater => {n.right = Self::insert_node(n.right.take(), value);}Ordering::Equal => {// 值已存在,不插入}}Some(n)}}}fn contains(&self, value: &T) -> bool {Self::contains_node(&self.root, value)}fn contains_node(node: &Option<Box<TreeNode<T>>>, value: &T) -> bool {match node {None => false,Some(n) => {match value.cmp(&n.value) {Ordering::Equal => true,Ordering::Less => Self::contains_node(&n.left, value),Ordering::Greater => Self::contains_node(&n.right, value),}}}}fn inorder_traversal(&self) -> Vec<&T> {let mut result = Vec::new();Self::inorder(&self.root, &mut result);result}fn inorder(node: &Option<Box<TreeNode<T>>>, result: &mut Vec<&T>) {if let Some(n) = node {Self::inorder(&n.left, result);result.push(&n.value);Self::inorder(&n.right, result);}}fn height(&self) -> usize {Self::calculate_height(&self.root)}fn calculate_height(node: &Option<Box<TreeNode<T>>>) -> usize {match node {None => 0,Some(n) => {let left_height = Self::calculate_height(&n.left);let right_height = Self::calculate_height(&n.right);1 + left_height.max(right_height)}}}fn len(&self) -> usize {self.size}
}fn demonstrate_bst() {let mut bst = BinarySearchTree::new();// 插入数据let values = vec![5, 3, 7, 1, 9, 4, 6];for val in values {bst.insert(val);}println!("树的大小: {}", bst.len());println!("树的高度: {}", bst.height());// 检查包含println!("包含 5? {}", bst.contains(&5));println!("包含 10? {}", bst.contains(&10));// 中序遍历(有序输出)let sorted = bst.inorder_traversal();println!("中序遍历: {:?}", sorted);
}// Rc<T> - 引用计数智能指针
use std::rc::Rc;fn rc_examples() {let data = Rc::new(vec![1, 2, 3, 4, 5]);println!("初始引用计数: {}", Rc::strong_count(&data));{let data2 = Rc::clone(&data);let data3 = Rc::clone(&data);println!("克隆后引用计数: {}", Rc::strong_count(&data));println!("data2: {:?}", data2);println!("data3: {:?}", data3);}println!("作用域结束后引用计数: {}", Rc::strong_count(&data));
}// 使用 Rc 实现图结构
use std::cell::RefCell;#[derive(Debug)]
struct GraphNode {id: usize,neighbors: RefCell<Vec<Rc<GraphNode>>>,
}impl GraphNode {fn new(id: usize) -> Rc<Self> {Rc::new(GraphNode {id,neighbors: RefCell::new(Vec::new()),})}fn add_neighbor(&self, neighbor: Rc<GraphNode>) {self.neighbors.borrow_mut().push(neighbor);}fn neighbors(&self) -> Vec<usize> {self.neighbors.borrow().iter().map(|n| n.id).collect()}
}fn demonstrate_graph() {let node1 = GraphNode::new(1);let node2 = GraphNode::new(2);let node3 = GraphNode::new(3);// 建立连接node1.add_neighbor(Rc::clone(&node2));node1.add_neighbor(Rc::clone(&node3));node2.add_neighbor(Rc::clone(&node3));println!("节点 1 的邻居: {:?}", node1.neighbors());println!("节点 2 的邻居: {:?}", node2.neighbors());println!("节点 1 的引用计数: {}", Rc::strong_count(&node1));
}// RefCell<T> - 内部可变性
struct Counter {count: RefCell<i32>,
}impl Counter {fn new() -> Self {Counter {count: RefCell::new(0),}}fn increment(&self) {*self.count.borrow_mut() += 1;}fn get(&self) -> i32 {*self.count.borrow()}fn reset(&self) {*self.count.borrow_mut() = 0;}
}fn demonstrate_refcell() {let counter = Counter::new();counter.increment();counter.increment();counter.increment();println!("计数: {}", counter.get());counter.reset();println!("重置后: {}", counter.get());
}// 组合 Rc 和 RefCell 实现共享可变状态
struct SharedList<T> {items: Rc<RefCell<Vec<T>>>,
}impl<T: Clone> SharedList<T> {fn new() -> Self {SharedList {items: Rc::new(RefCell::new(Vec::new())),}}fn add(&self, item: T) {self.items.borrow_mut().push(item);}fn clone_list(&self) -> SharedList<T> {SharedList {items: Rc::clone(&self.items),}}fn get_all(&self) -> Vec<T> {self.items.borrow().clone()}fn len(&self) -> usize {self.items.borrow().len()}
}fn demonstrate_shared_list() {let list1 = SharedList::new();let list2 = list1.clone_list();list1.add("Rust");list2.add("is");list1.add("awesome");println!("列表 1: {:?}", list1.get_all());println!("列表 2: {:?}", list2.get_all());println!("两者共享同一数据!");
}fn main() {println!("=== Box 示例 ===");box_examples();println!("\n=== 二叉搜索树 ===");demonstrate_bst();println!("\n=== Rc 示例 ===");rc_examples();println!("\n=== 图结构 ===");demonstrate_graph();println!("\n=== RefCell 示例 ===");demonstrate_refcell();println!("\n=== 共享列表 ===");demonstrate_shared_list();
}
智能指针对比
| 类型 | 所有权 | 可变性 | 线程安全 |
|---|---|---|---|
| Box | 独占 | 取决于 mut | 是 |
| Rc | 共享 | 不可变 | 否 |
| Arc | 共享 | 不可变 | 是 |
| RefCell | 独占 | 内部可变 | 否 |
| Mutex | 共享 | 内部可变 | 是 |
总结
智能指针是 Rust 中管理内存和实现复杂数据结构的强大工具。选择合适的智能指针可以让代码更加安全和高效。
