Rust语言

关注公众号 jb51net

关闭
首页 > 软件编程 > Rust语言 > Rust 智能指针

Rust 智能指针的使用详解

作者:小灰灰搞电子

Rust智能指针是内存管理核心工具,本文就来详细的介绍一下Rust智能指针(Box、Rc、RefCell、Arc、Mutex、RwLock、Weak)的原理与使用场景,感兴趣的可以了解一下

一、Rust 智能指针详解

智能指针是Rust中管理内存和所有权的核心工具,通过封装指针并添加元数据(如引用计数)来实现安全的内存管理。以下是主要类型及其原理、使用场景和示例:

1、Box<T>:堆内存分配

2、Rc<T>:引用计数指针

3、RefCell<T>:内部可变性

4、Arc<T>:原子引用计数

5、Mutex<T>与RwLock<T>:线程同步

6、Weak<T>:解决循环引用

7、组合模式

8、对比总结

类型线程安全可变性适用场景
Box<T>所有权唯一堆分配、递归类型
Rc<T>不可变共享单线程共享只读数据
RefCell<T>内部可变单线程运行时借用检查
Arc<T>不可变共享多线程共享只读数据
Mutex<T>线程安全可变多线程互斥修改数据
RwLock<T>读写分离读多写少场景

二、Rust 智能指针示例

以下是一个复杂的 Rust 智能指针示例,结合了 RcRefCell 和自定义智能指针,模拟图形渲染场景中的资源管理:

use std::rc::{Rc, Weak};
use std::cell::RefCell;
use std::ops::Deref;

// 自定义智能指针:带引用计数的纹理资源
struct Texture {
    id: u32,
    data: Vec<u8>,
}

impl Texture {
    fn new(id: u32, size: usize) -> Self {
        Texture {
            id,
            data: vec![0; size],
        }
    }
}

// 自定义智能指针:TextureHandle
struct TextureHandle(Rc<Texture>);

impl TextureHandle {
    fn new(texture: Texture) -> Self {
        TextureHandle(Rc::new(texture))
    }
    
    fn get_id(&self) -> u32 {
        self.0.id
    }
}

impl Deref for TextureHandle {
    type Target = Texture;
    
    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

// 场景节点:支持父子关系
struct SceneNode {
    name: String,
    texture: Option<TextureHandle>,
    children: RefCell<Vec<Rc<RefCell<SceneNode>>>>,
    parent: RefCell<Weak<RefCell<SceneNode>>>,
}

impl SceneNode {
    fn new(name: &str) -> Rc<RefCell<Self>> {
        Rc::new(RefCell::new(SceneNode {
            name: name.to_string(),
            texture: None,
            children: RefCell::new(Vec::new()),
            parent: RefCell::new(Weak::new()),
        }))
    }
    
    fn add_child(parent: &Rc<RefCell<SceneNode>>, child: &Rc<RefCell<SceneNode>>) {
        child.borrow_mut().parent.replace(Rc::downgrade(parent));
        parent.borrow_mut().children.borrow_mut().push(Rc::clone(child));
    }
    
    fn set_texture(&mut self, texture: TextureHandle) {
        self.texture = Some(texture);
    }
    
    fn print_tree(&self, depth: usize) {
        let indent = "  ".repeat(depth);
        println!("{}{}", indent, self.name);
        if let Some(tex) = &self.texture {
            println!("{}Texture ID: {}", indent, tex.get_id());
        }
        for child in self.children.borrow().iter() {
            child.borrow().print_tree(depth + 1);
        }
    }
}

fn main() {
    // 创建共享纹理资源
    let shared_texture = TextureHandle::new(Texture::new(101, 1024));
    
    // 创建场景节点
    let root = SceneNode::new("Root");
    let camera = SceneNode::new("Camera");
    let mesh1 = SceneNode::new("Mesh1");
    let mesh2 = SceneNode::new("Mesh2");
    
    // 设置纹理
    {
        let mut root_mut = root.borrow_mut();
        root_mut.set_texture(shared_texture);
    }
    
    // 构建场景层级
    SceneNode::add_child(&root, &camera);
    SceneNode::add_child(&root, &mesh1);
    SceneNode::add_child(&mesh1, &mesh2);
    
    // 打印场景树
    root.borrow().print_tree(0);
    
    // 验证引用计数
    println!("\nReference counts:");
    println!("Root strong: {}", Rc::strong_count(&root));
    println!("Root weak: {}", Rc::weak_count(&root));
}

示例解析:

  1. 自定义智能指针 TextureHandle

    • 包装 Rc<Texture> 实现资源共享
    • 实现 Deref 获得透明访问
    • 提供资源 ID 访问方法
  2. 场景图管理 SceneNode

    • 使用 Rc<RefCell<SceneNode>> 实现共享所有权和内部可变性
    • 子节点列表:RefCell<Vec<Rc<...>>> 实现运行时可变借用
    • 父节点:RefCell<Weak<...>> 避免循环引用
  3. 资源共享机制

    • 纹理资源通过 TextureHandle 共享
    • 节点树通过 Rc 共享所有权
    • 使用 Weak 引用打破循环依赖
  4. 输出示例

Root
Texture ID: 101
  Camera
  Mesh1
    Mesh2

Reference counts:
Root strong: 1
Root weak: 2
PS G:\Learning\Rust\ttt> 

关键特性:

  1. 内存安全:自动管理资源释放
  2. 内部可变性:通过 RefCell 修改不可变引用
  3. 循环引用防护:Weak 指针避免内存泄漏
  4. 透明访问:通过 Deref 实现直接访问
  5. 运行时借用检查:RefCell 在运行时验证借用规则

到此这篇关于Rust 智能指针的使用详解的文章就介绍到这了,更多相关Rust 智能指针内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:
阅读全文