智能指针完全指南

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 中管理内存和实现复杂数据结构的强大工具。选择合适的智能指针可以让代码更加安全和高效。

相关推荐
Java水解18 小时前
Rust嵌入式开发实战——从ARM裸机编程到RTOS应用
后端·rust
Pomelo_刘金19 小时前
Rust:所有权系统
rust
Ranger09291 天前
鸿蒙开发新范式:Gpui
rust·harmonyos
埃博拉酱4 天前
VS Code Remote SSH 连接 Windows 服务器卡在"下载 VS Code 服务器":prcdn DNS 解析失败的诊断与 BITS 断点续传
windows·ssh·visual studio code
DongLi014 天前
rustlings 学习笔记 -- exercises/05_vecs
rust
唐宋元明清21885 天前
.NET 本地Db数据库-技术方案选型
windows·c#
加号35 天前
windows系统下mysql多源数据库同步部署
数据库·windows·mysql
tryCbest5 天前
Windows环境下配置pip镜像源
windows·pip
呉師傅5 天前
火狐浏览器报错配置文件缺失如何解决#操作技巧#
运维·网络·windows·电脑
百事牛科技5 天前
保护文档安全:PDF限制功能详解与实操
windows·pdf