MST

星途 面试题库

面试题:Rust中栈内存和堆内存的分配机制

请详细阐述在Rust语言中,栈内存和堆内存分别在哪些情况下会进行分配?例如对于简单数据类型和复杂自定义结构体类型,它们的内存分配有何不同?
29.7万 热度难度
编程语言Rust

知识考点

AI 面试

面试题答案

一键面试

栈内存分配情况

  1. 简单数据类型:在Rust中,像整数(如 i32u8 等)、浮点数(f32f64)、布尔值(bool)、字符(char)以及元组(tuple),只要其所有元素都是固定大小类型,这些简单数据类型在声明时通常分配在栈上。例如:
let num: i32 = 42;
let flag: bool = true;
let point: (i32, i32) = (10, 20);

这里的 numflagpoint 都在栈上分配内存,因为它们的大小在编译时是已知的。

  1. 函数参数和局部变量:函数参数和在函数内部声明的局部变量,如果它们是简单数据类型或者固定大小的复合类型,也是在栈上分配。例如:
fn add_numbers(a: i32, b: i32) -> i32 {
    let sum = a + b;
    sum
}

这里的 absum 都在栈上分配内存。

堆内存分配情况

  1. 复杂自定义结构体类型:如果自定义结构体包含动态大小的类型(如 StringVec<T> 等),那么整个结构体实例会在堆上分配。例如:
struct Person {
    name: String,
    age: i32,
}

let person = Person {
    name: String::from("Alice"),
    age: 30,
};

这里的 person 实例会在堆上分配,因为 name 字段是 String 类型,其大小在编译时不确定,需要在运行时根据字符串内容分配内存。

  1. 使用 Box<T> 等智能指针:当使用 Box<T> 来包装类型时,被包装的类型会在堆上分配。例如:
let boxed_num = Box::new(42);

这里的 42 原本是栈上分配的 i32 类型,但通过 Box::new 包装后,boxed_num 指向堆上分配的 i32 数据。这种方式常用于需要在堆上分配单个值,并且希望在栈上有一个指向堆数据的句柄的场景。

  1. 动态大小类型(DST):Rust中的动态大小类型,如 str(字符串切片,与 String 不同)和 trait 对象,总是在堆上分配。例如:
let s: &str = "hello";

虽然 s 本身是栈上的引用,但它指向的字符串数据 "hello" 存储在静态存储区(类似堆的概念,在程序加载时分配)。当使用 String 时,它是 str 的拥有者类型,在堆上分配内存来存储字符串内容:

let string = String::from("world");

这里的 string 实例在堆上分配内存来存储字符串 "world"