深入Rust智能指针和模式匹配

目录智能指针Box堆对象分配Deref解引用Drop释放资源Rc与Arc实现1vN所有权机制Cell与RefCell内部可变性模式和匹配智能指针Box堆对象分配什么是Box?Box是一个智能指针,它在堆上分配对象。Box自动管理内存,当不再需要时会自动释

目录


智能指针

Box 堆对象分配

什么是 Box?

  • Box 是一个智能指针,它在堆上分配对象。
  • Box 自动管理内存,当不再需要时会自动释放。
fn main() {
    // 在堆上分配一个整数
    let boxed_num = Box::new(42);
    println!("Boxed number: {}", boxed_num); // 输出: Boxed number: 42

    // 解引用
    let num = *boxed_num;
    println!("Unboxed number: {}", num); // 输出: Unboxed number: 42
}

Deref 解引用

什么是 Deref 特征?

  • Deref 特征使得智能指针可以像普通变量一样使用。
  • Deref 特征定义了如何解引用智能指针。
use std::ops::Deref;

struct MyBox<T>(T);

impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

fn main() {
    let my_box = MyBox(42);
    println!("MyBox value: {}", *my_box); // 输出: MyBox value: 42
}

Drop 释放资源

什么是 Drop 特征?

  • Drop 特征允许在智能指针被丢弃时执行清理操作。
  • Drop 特征定义了如何释放资源。
struct MyResource {
    name: String,
}

impl Drop for MyResource {
    fn drop(&mut self) {
        println!("Dropping resource: {}", self.name);
    }
}

fn main() {
    {
        let res = MyResource { name: String::from("Resource A") };
        println!("Resource created: {}", res.name); // 输出: Resource created: Resource A
    } // 在这里,资源会被自动释放

    println!("After resource dropped"); // 输出: After resource dropped
}

Rc 实现 1vN 所有权机制

什么是 Rc?

  • Rc(Reference Counted)是一个智能指针,用于实现共享所有权。
  • Rc 通过引用计数来管理内存。
use std::rc::Rc;

fn main() {
    let a = Rc::new(String::from("Hello"));
    println!("Count after creating a: {}", Rc::strong_count(&a)); // 输出: Count after creating a: 1

    let b = a.clone();
    println!("Count after cloning a into b: {}", Rc::strong_count(&a)); // 输出: Count after cloning a into b: 2

    {
        let c = a.clone();
        println!("Count after cloning a into c: {}", Rc::strong_count(&a)); // 输出: Count after cloning a into c: 3
    } // 在这里,c 被释放,引用计数减 1

    println!("Count after c goes out of scope: {}", Rc::strong_count(&a)); // 输出: Count after c goes out of scope: 2
}

Arc 实现 1vN 所有权机制

什么是 Arc?

  • Arc(Atomic Reference Counted)是一个智能指针,用于实现多线程共享所有权。
  • Arc 通过原子引用计数来管理内存。
use std::sync::Arc;

fn main() {
    let a = Arc::new(String::from("Hello"));
    println!("Count after creating a: {}", Arc::strong_count(&a)); // 输出: Count after creating a: 1

    let b = a.clone();
    println!("Count after cloning a into b: {}", Arc::strong_count(&a)); // 输出: Count after cloning a into b: 2

    {
        let c = a.clone();
        println!("Count after cloning a into c: {}", Arc::strong_count(&a)); // 输出: Count after cloning a into c: 3
    } // 在这里,c 被释放,引用计数减 1

    println!("Count after c goes out of scope: {}", Arc::strong_count(&a)); // 输出: Count after c goes out of scope: 2
}

Cell 与 RefCell 内部可变性

什么是 Cell?

  • Cell 提供了内部可变性,可以在不可变引用的情况下修改值。
  • Cell 适用于单线程场景。
use std::cell::Cell;

fn main() {
    let mut cell = Cell::new(0);
    println!("Initial value: {}", cell.get()); // 输出: Initial value: 0

    cell.set(42);
    println!("New value: {}", cell.get()); // 输出: New value: 42
}

什么是 RefCell?

  • RefCell 提供了内部可变性,并且支持借用检查。
  • RefCell 适用于单线程场景,可以确保借用规则。
use std::cell::RefCell;

fn main() {
    let mut refcell = RefCell::new(0);
    println!("Initial value: {}", *refcell.borrow()); // 输出: Initial value: 0

    *refcell.borrow_mut() = 42;
    println!("New value: {}", *refcell.borrow()); // 输出: New value: 42
}

RefCell 与借用检查

  • RefCell 支持借用检查,可以确保借用规则。
  • RefCell 可以在运行时检查借用。
use std::cell::RefCell;

fn main() {
    let refcell = RefCell::new(0);

    {
        let borrowed = refcell.borrow();
        println!("Borrowed value: {}", *borrowed); // 输出: Borrowed value: 0

        // 无法同时借用不可变引用和可变引用
        // let borrowed_mut = refcell.borrow_mut(); // 错误
    }

    {
        let borrowed_mut = refcell.borrow_mut();
        *borrowed_mut = 42;
        println!("Mutated value: {}", *borrowed_mut); // 输出: Mutated value: 42
    }
}

RefCell 与多层借用

多层借用示例

  • RefCell 可以嵌套使用,支持多层借用。
  • 多层借用可以实现复杂的借用逻辑。
use std::cell::RefCell;

fn main() {
    let outer_refcell = RefCell::new(0);
    let inner_refcell = RefCell::new(outer_refcell);

    {
        let outer_borrowed = inner_refcell.borrow();
        println!("Outer borrowed value: {}", *outer_borrowed.borrow()); // 输出: Outer borrowed value: 0

        *outer_borrowed.borrow_mut() = 42;
        println!("Outer mutated value: {}", *outer_borrowed.borrow()); // 输出: Outer mutated value: 42
    }

    {
        let inner_borrowed = inner_refcell.borrow();
        println!("Inner borrowed value: {}", *inner_borrowed.borrow()); // 输出: Inner borrowed value: 42
    }
}

RefCell 与多线程

多线程示例

  • RefCell 适用于单线程场景。
  • 多线程场景需要使用 Mutex 或 Arc<Mutex>

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

fn main() {
    let shared_data = Arc::new(Mutex::new(0));

    let thread1_data = Arc::clone(&shared_data);
    let thread2_data = Arc::clone(&shared_data);

    let handle1 = thread::spawn(move || {
        let mut data = thread1_data.lock().unwrap();
        *data += 1;
        println!("Thread 1 value: {}", *data); // 输出: Thread 1 value: 1
    });

    let handle2 = thread::spawn(move || {
        let mut data = thread2_data.lock().unwrap();
        *data += 2;
        println!("Thread 2 value: {}", *data); // 输出: Thread 2 value: 3
    });

    handle1.join().unwrap();
    handle2.join().unwrap();...

剩余50%的内容订阅专栏后可查看

点赞 0
收藏 0
分享
本文参与登链社区写作激励计划 ,好文好收益,欢迎正在阅读的你也加入。

0 条评论

请先 登录 后评论