智能指针完全指南

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 小时前
键盘改键工具免安装,自定义键位屏蔽误触
java·网络·windows·随机森林·计算机外设·电脑·excel
2601_949532842 小时前
Psello HTML Template: A Developer‘s Deep-Dive Review and Guide - Download Free
前端·windows·html·seo·wordpress·gpl
软件资深者4 小时前
USB存储设备管理工具 启用或者禁用+usb修复
windows·microsoft·计算机外设·系统修复
失眠的稻草人2594 小时前
【windows】注入--BHO机制
windows
XLYcmy4 小时前
一个用于统计文本文件行数的Python实用工具脚本
开发语言·数据结构·windows·python·开发工具·数据处理·源代码
程序员徐师兄4 小时前
Windows JDK17 下载安装教程,附详细图文
java·windows·jdk17 下载安装·java17 下载安装教程
80530单词突击赢4 小时前
C++STL list实现揭秘
windows
myjie05275 小时前
使用 windows ndk-stack 分析NDK crash
windows
小邓睡不饱耶6 小时前
使用Scala实现手机号码归属地查询系统
开发语言·windows·scala
0白露6 小时前
关闭搜狗输入法右下角广告,可以适用于大多数应用系统通知的广告
windows·bug