MST

星途 面试题库

面试题:Rust 智能指针与内存分配

Rust 中有 `Box`、`Rc`、`Arc` 等智能指针类型,分析它们在内存分配和管理上的不同机制,以及在多线程环境下 `Arc` 相较于 `Rc` 在内存分配与共享上的优势,并结合具体代码示例说明。
25.5万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

Box

  1. 内存分配机制Box 用于在堆上分配数据,将数据的所有权转移到 Box 中。它分配一块连续的内存来存储数据。
  2. 内存管理机制:当 Box 离开作用域时,它所指向的数据会被自动释放,遵循 Rust 的所有权和生命周期规则。

示例代码:

fn main() {
    let b = Box::new(5);
    println!("b contains: {}", b);
}

Rc

  1. 内存分配机制Rc(引用计数)允许在堆上分配的数据被多个所有者共享。它内部除了存储指向数据的指针外,还维护一个引用计数。每次克隆 Rc,引用计数加一。
  2. 内存管理机制:当 Rc 的引用计数降为 0 时,所指向的数据会被释放。

示例代码:

use std::rc::Rc;

fn main() {
    let a = Rc::new(5);
    let b = a.clone();
    println!("a reference count: {}", Rc::strong_count(&a));
    println!("b reference count: {}", Rc::strong_count(&b));
}

Arc

  1. 内存分配机制Arc(原子引用计数)与 Rc 类似,也是通过引用计数来管理内存,允许数据在多个所有者间共享。但 Arc 使用原子操作来管理引用计数,这使得它线程安全。
  2. 内存管理机制:当 Arc 的引用计数降为 0 时,所指向的数据会被释放。

Arc 在多线程环境下相较于 Rc 的优势

Rc 不是线程安全的,因为其引用计数的操作不是原子的,在多线程环境下可能会导致数据竞争。而 Arc 使用原子操作管理引用计数,适合多线程环境。

示例代码:

use std::sync::Arc;
use std::thread;

fn main() {
    let data = Arc::new(5);
    let handles = (0..10).map(|_| {
        let data = data.clone();
        thread::spawn(move || {
            println!("Thread sees data: {}", data);
        })
    }).collect::<Vec<_>>();

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

在上述代码中,如果将 Arc 替换为 Rc,编译时会报错,因为 Rc 不能跨线程传递,而 Arc 由于其原子引用计数机制,可以安全地在多线程环境下共享数据。