Rust 智能指针完全指南
简介
智能指针是一类数据结构,它们的行为类似于指针,但拥有额外的元数据和功能。Rust 标准库提供了多种智能指针,用于不同的场景。
主要智能指针类型
Box<T>- 堆上分配Rc<T>- 引用计数Arc<T>- 原子引用计数RefCell<T>- 内部可变性Mutex<T>- 互斥锁
Box - 堆分配
Box 是最简单的智能指针,用于在堆上分配值。
rust
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 实现一个功能完整的二叉搜索树:
rust
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 中管理内存和实现复杂数据结构的强大工具。选择合适的智能指针可以让代码更加安全和高效。