智能指针完全指南

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

相关推荐
梦帮科技2 小时前
OpenClaw 桥接调用 Windows MCP:打造你的 AI 桌面自动化助手
人工智能·windows·自动化
春日见3 小时前
如何创建一个PR
运维·开发语言·windows·git·docker·容器
C++ 老炮儿的技术栈3 小时前
VS2015 + Qt 实现图形化Hello World(详细步骤)
c语言·开发语言·c++·windows·qt
浩浩测试一下4 小时前
内网---> WriteOwner权限滥用
网络·汇编·windows·安全·microsoft·系统安全
微小冷4 小时前
Rust异步编程详解
开发语言·rust·async·await·异步编程·tokio
鸿乃江边鸟4 小时前
Spark Datafusion Comet 向量化Rust Native--CometShuffleExchangeExec怎么控制读写
大数据·rust·spark·native
一个人旅程~4 小时前
Dell n4020双系统分区步骤和linux优化操作
linux·windows·电脑
love530love5 小时前
【高阶编译】Windows 环境下强制编译 Flash Attention:绕过 CUDA 版本不匹配高阶指南
人工智能·windows·python·flash_attn·flash-attn·flash-attention·定制编译
勾股导航5 小时前
Windows安装GPU环境
人工智能·windows·gnu
x***r1515 小时前
PhpStudy2018怎么用?完整安装与使用指南(新手必看)
windows