智能指针完全指南

Rust 智能指针完全指南

简介

智能指针是一类数据结构,它们的行为类似于指针,但拥有额外的元数据和功能。Rust 标准库提供了多种智能指针,用于不同的场景。

主要智能指针类型

  1. Box<T> - 堆上分配
  2. Rc<T> - 引用计数
  3. Arc<T> - 原子引用计数
  4. RefCell<T> - 内部可变性
  5. 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 中管理内存和实现复杂数据结构的强大工具。选择合适的智能指针可以让代码更加安全和高效。

相关推荐
马士兵教育5 分钟前
RocketMQ如何进行性能调优?
服务器·windows·rocketmq
fundoit1 小时前
Windows 下 YOLO 环境搭建与使用完整指南
windows·yolo
乔宕一2 小时前
windows SSH服务修改SSH登陆后的默认终端
运维·windows·ssh
love530love2 小时前
ComfyUI-3D-Pack:Windows 下手动编译 mesh_inpaint_processor C++ 加速模块
c++·人工智能·windows·python·3d·hunyuan3d·comfyui-3d-pack
oyzz1203 小时前
Windows 上彻底卸载 Node.js
windows·node.js
闭关苦炼内功3 小时前
Win10 安装 MySQL5.7.36 数据库记录
数据库·windows·mysql
Rust研习社4 小时前
为什么错误返回在工程实践中要优于异常捕获
rust
斯密码赛我是美女4 小时前
周报(欢乐赛+信息搜集ctfshow+Trae-mcp)
网络·windows
米饭不加菜5 小时前
Windows 键盘快捷方式总览
windows·计算机外设
Luna-player5 小时前
Sass与stylus的区别
rust·sass·stylus