Rust语言

关注公众号 jb51net

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

rust中智能指针的实现

作者: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());
}

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 的底层支撑

总结建议

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

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