智能指针完全指南

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

相关推荐
想唱rap4 小时前
C++list类的模拟实现
linux·运维·服务器·数据结构·c++·windows·list
H_z_q24014 小时前
Python测试题1
windows
汤愈韬5 小时前
域网络,域环境搭建
windows·网络安全
G_dou_5 小时前
并发编程基础
算法·rust
ai安歌7 小时前
【Rust编程:从新手到大师】 Rust 控制流深度详解
开发语言·算法·rust
G_dou_9 小时前
借用与引用实战
rust
The 旺10 小时前
【Rust实战】打造内存安全的网络代理:深入异步IO与并发编程
网络·安全·rust
namekong811 小时前
导入的 Google(Chrome)书签默认不会自动显示在「书签栏」,而是放在一个文件夹里。下面是详细步骤,帮你把 导入的全部书签添加到书签栏
windows
RustCoder12 小时前
RustNet:使用 Rust 开发的跨平台网络监控工具
安全·rust·开源