rust中智能指针的实现

 更新时间:2025年06月27日 09:44:02   作者:pumpkin84514  
Rust智能指针通过所有权实现资源自动管理,包含Box、Rc、Arc、Mutex等类型,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧

1、 什么是智能指针?Rust 三类指针对比

类型安全性借用检查是否自动释放功能特点
&T, &mut T✅ 是✅ 是✅ 是借用引用,不拥有数据
*const T, *mut T❌ 否❌ 否❌ 否原生裸指针,用于 FFI、底层控制
智能指针(如 Box)✅ 是✅ 是/部分✅ 是拥有数据,带有自动释放和额外功能

📌 智能指针本质是一个拥有值的结构体,实现了 Deref 和 Drop,让你可以像指针一样访问值,又能自动释放资源。

2、原生指针 *const T:危险但有用

fn main() {
    let x = 5;
    let p: *const i32 = &x; // 获取原生指针

    unsafe {
        println!("值是:{}", *p); // 只有在 unsafe 代码块中才能解引用
    }
}

✅ 只读,不会自动释放。
❌ 无生命周期、越界检查,容易悬垂。
💡 用于与 C 语言交互或实现底层结构。

手动释放:Box::into_raw / from_raw

fn main() {
    let b = Box::new(42);
    let ptr = Box::into_raw(b);         // 转换为裸指针,不再自动释放

    unsafe {
        let b2 = Box::from_raw(ptr);    // 重新接管所有权
        println!("恢复值:{}", b2);
    } // 自动释放
}

📌 记住:谁 into_raw,谁就必须 from_raw,否则泄漏!

3、常见智能指针逐个讲清

Box:在堆上分配值

fn main() {
    let b = Box::new(100);              // 将整数 100 放到堆上
    println!("b 的值是:{}", *b);       // 解引用访问
} // 离开作用域自动释放(RAII)

适合:大对象、递归结构、强制所有权转移。

Rc:单线程引用计数共享

use std::rc::Rc;

fn main() {
    let a = Rc::new("hello".to_string());
    let b = Rc::clone(&a);              // 引用计数 +1
    println!("a = {}, b = {}", a, b);   // 多个变量共享同一块内存
}

适合:多个地方共享不可变数据,如图结构、缓存。
📛 注意:不能用于多线程。

RefCell / Cell:内部可变性

use std::cell::RefCell;

fn main() {
    let x = RefCell::new(10);           // 创建可变容器
    *x.borrow_mut() += 5;               // 可变借用
    println!("当前值: {}", x.borrow());
}
  • RefCell:运行时借用检查,支持引用。
  • Cell:适合 Copy 类型的值,用 get/set 读写。

Cow:写时复制,节省资源

use std::borrow::Cow;

fn modify(input: Cow<str>) -> Cow<str> {
    if input.contains("x") {
        Cow::Owned(input.replace("x", "y")) // 真要改时才复制
    } else {
        input
    }
}

fn main() {
    let s = Cow::Borrowed("hexo");
    let result = modify(s);
    println!("结果:{}", result);
}

适合:读取多、写入少的场景,如配置、模板处理。

Option 与智能指针

fn get_name() -> Option<&'static str> {
    Some("Tom")
}

fn main() {
    if let Some(name) = get_name() {
        println!("找到名字:{}", name);
    }
}

Option 表示“可能有值”或“无值”,智能指针经常作为 Option 的值使用,用于“延迟初始化”。

4、 并发智能指针

Arc:线程安全引用计数

use std::sync::Arc;

fn main() {
    let a = Arc::new(42);
    let b = Arc::clone(&a);
    println!("a = {}, b = {}", a, b);
}

🧠 与 Rc 类似,但用原子操作实现,适合多线程。

Mutex:互斥锁保护数据

use std::sync::Mutex;

fn main() {
    let m = Mutex::new(0);
    {
        let mut data = m.lock().unwrap();
        *data += 1;
    }
    println!("当前值: {:?}", m);
}

📌 一次只能一个线程修改。

RwLock:读多写少,效率高

use std::sync::RwLock;

fn main() {
    let lock = RwLock::new(10);

    {
        let r1 = lock.read().unwrap();
        let r2 = lock.read().unwrap();
        println!("读者1: {}, 读者2: {}", r1, r2);
    }

    {
        let mut w = lock.write().unwrap();
        *w += 10;
    }

    println!("写后值: {}", *lock.read().unwrap());
}

AtomicUsize:无锁计数器

use std::sync::atomic::{AtomicUsize, Ordering};

fn main() {
    let counter = AtomicUsize::new(0);
    counter.fetch_add(1, Ordering::SeqCst); // 原子 +1
    println!("计数器值: {}", counter.load(Ordering::SeqCst));
}

适合:高性能并发状态计数,如连接数、任务状态。

5、高阶用法组合:Arc<Mutex>

use std::sync::{Arc, Mutex};
use std::thread;

fn main() {
    let counter = Arc::new(Mutex::new(0));
    let mut handles = vec![];

    for _ in 0..10 {
        let c = Arc::clone(&counter);
        let handle = thread::spawn(move || {
            let mut num = c.lock().unwrap();
            *num += 1;
        });
        handles.push(handle);
    }

    for h in handles {
        h.join().unwrap();
    }

    println!("最终结果: {}", *counter.lock().unwrap());
}

6、深入进阶:Weak / Pin / UnsafeCell

Weak:打破 Rc/Arc 的循环引用

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

struct Node {
    next: RefCell<Option<Rc<Node>>>,
    prev: RefCell<Option<Weak<Node>>>, // 使用弱引用避免循环
}

📌 Rc::downgrade(&rc) 转换为 Weak,不计入引用计数
📌 .upgrade() 返回 Option<Rc>

Pin:防止对象被移动

use std::pin::Pin;

fn main() {
    let data = String::from("hello");
    let pinned = Pin::new(&data);
    println!("{}", pinned);
}

📌 用于 Future、self-referential 结构
📌 Box::pin() 可固定对象

UnsafeCell:RefCell/Mutex 背后的魔法

use std::cell::UnsafeCell;

struct MyType {
    data: UnsafeCell<i32>,
}

unsafe impl Sync for MyType {}

fn main() {
    let x = MyType { data: UnsafeCell::new(0) };

    unsafe {
        *x.data.get() = 42;
        println!("{}", *x.data.get());
    }
}

📌 允许穿透不可变引用进行修改,底层实现 RefCell、Mutex

场景速查表

类型线程安全可变性常见用途
Box❌ 否✅ 是所有权转移,递归结构
Rc❌ 否❌ 否单线程共享只读数据
RefCell❌ 否✅ 是内部可变性,运行时借用检查
Cell❌ 否✅ 是Copy 类型小数据的替换
Cow✅ 是✅ 是写时复制,节省资源
Arc✅ 是❌ 否多线程只读共享
Mutex✅ 是✅ 是多线程可变共享
RwLock✅ 是✅ 是多读单写
AtomicUsize✅ 是✅ 是无锁计数器,高性能状态共享
Weak✅ 是❌ 否打破 Rc/Arc 循环引用
Pin✅ 是❌ 否防止移动,适用于异步/自引用结构
UnsafeCell❌(需手动保证)✅ 是RefCell / Mutex 的底层支撑

总结建议

  • 智能指针 = 拥有数据 + 自动管理资源 + 像引用一样使用
  • Rc、RefCell 是组合神器,但要小心引用环
  • Arc + Mutex 是并发安全的常见搭配
  • 遇到底层问题,了解 Pin / UnsafeCell 能更深入掌握 Rust 内存模型

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

相关文章

  • 利用rust编一个静态博客工具

    利用rust编一个静态博客工具

    这篇文章主要为大家详细介绍了如何利用rust编一个静态博客工具,这个静态博客的工具主要是把md文档转为html静态网站/博客,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-12-12
  • 如何使用Rust的向量存储值列表

    如何使用Rust的向量存储值列表

    本文介绍了在Rust中使用向量存储值列表的方法,包括创建、更新、读取、遍历、存储多种类型以及内存释放等方面,向量是Rust中常用且强大的集合类型,熟练掌握其用法有助于编写高效且安全的代码
    2025-02-02
  • 浅析Rust多线程中如何安全的使用变量

    浅析Rust多线程中如何安全的使用变量

    这篇文章主要为大家详细介绍了Rust如何在线程的闭包中安全的使用变量,包括共享变量和修改变量,文中的示例代码讲解详细,有需要的小伙伴可以参考下
    2025-01-01
  • 详解Rust Substrate框架中的Runtime

    详解Rust Substrate框架中的Runtime

    ubstrate是一个区块链开发框架,它提供了一系列模块化和可扩展的组件,可以帮助开发人员快速构建自定义区块链。 Runtime是Substrate区块链的核心部分,文中有详细的代码示例,需要的朋友可以参考下
    2023-05-05
  • 通过rust实现自己的web登录图片验证码功能

    通过rust实现自己的web登录图片验证码功能

    本文介绍了如何使用Rust和imagecrate库生成图像验证码,首先,通过Cargo.toml文件添加image依赖,然后,生成纯色图片并编辑验证图片,接着,编写随机函数获取字符,并通过循环生成验证码图片,最终,通过运行函数验证验证码图片是否生成,感兴趣的朋友一起看看吧
    2025-03-03
  • Rust中用enum实现多参数Hook机制完整代码

    Rust中用enum实现多参数Hook机制完整代码

    在 Rust 中,如果想为enum实现一个带多参数的 Hook 机制,可以结合模式匹配和枚举来处理,这种方式可以扩展到支持不同类型的输入参数和逻辑处理,下面通过示例代码介绍Rust中用enum实现多参数Hook机制,感兴趣的朋友一起看看吧
    2024-12-12
  • Rust调用C程序的实现步骤

    Rust调用C程序的实现步骤

    本文主要介绍了Rust调用C程序的实现步骤,包括创建C函数、编译C代码、链接Rust和C代码等步骤,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12
  • R语言ggplot2绘图安装与调试

    R语言ggplot2绘图安装与调试

    ggplot2是R语言中最常用的绘图包之一,它提供了一种基于图层的绘图语法,使得用户可以轻松地创建高质量的数据可视化图表。在使用ggplot2之前,需要先安装该包并进行调试。安装ggplot2可以通过CRAN或GitHub进行,调试则需要注意数据格式、语法错误等问题。
    2023-06-06
  • Rust 原始指针功能探索

    Rust 原始指针功能探索

    这篇文章主要为大家介绍了Rust 原始指针功能探索,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-10-10
  • rust中间件actix_web在项目中的使用实战

    rust中间件actix_web在项目中的使用实战

    这篇文章主要介绍了rust中间件在项目中的使用实战,包括自定义中间件,日志中间件,Default headers,用户会话,错误处理的用法实例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2024-01-01

最新评论