Rust 中的Box指针使递归类型成为可能 - Knoldus Blogs


指针是包含在存储器中的地址的变量的一般概念的编程。Rust智能指针是一种数据结构,不仅可以充当指针,还具有额外的元数据和功能。Box指针是 Rust 中的智能指针之一。
Box指针让您将数据存储在堆上而不是栈上,保存在栈上的就是指向堆中数据的指针。

let ptr = Box::new(25);

我们在以下情况下使用 Box –

  • 当您的类型在编译时无法知道其大小,并且您想在需要精确大小的上下文中使用该类型的值时
  • 如果您有大量数据并且想要转移所有权,但要确保这样做时不会复制数据
  • 当你想拥有一个值并且你只关心它是一个实现特定特征的类型而不是特定类型时

 
使用 Box Type类型 存储数据
正如我们上面讨论的,box Type类型用于在堆上而不是栈上存储数据。指向堆上数据的指针确实存储在栈中。这里有一个例子可以更好地解释它。
fn main() {
    let ptr = Box::new("hello");
    println!(
"The pointer points to data : {}", ptr);
}

在上面的示例中,有一个变量ptr存储指向字符串“hello”的Box 指针。字符串 hello 在堆上,box指针ptr在栈上。该程序将打印以下内容 :

The pointer points to data : hello

PTR变量拥有Box指针,因此规则的所有权适用于它。随着main方法的结束,ptr box指针指向的内存会被释放,栈上的box指针也会被释放。
 
使用Box指针的递归类型
在任何编程语言中,编译器都需要知道任何数据类型占用的空间。这对于 Rust Compiler 来说是一样的,但是在递归 类型的情况下,这是相当困难的,递归类型其中值可以具有作为自身的一部分的另一值相同类型,编译器不知道在编译时为这种数据类型分配多少内存。这里有一个例子可以更好地解释它。
enum RecType {
    Cons(i32, Rectype),
    Nil,
}

这里,RecType是一个递归枚举,它有一个与元组 (i32, RecType)相关联的变体。该元组包含一个i32值和一个相同类型的值,即RecType。因此,在这种情况下,编译器在编译时很难为RecType分配空间。
为了克服这个问题,我们可以使用Box 指针。由于我们可以知道Box 指针在编译时占用的空间,因此我们可以在元组中使用Box 指针来指向RecType类型的值。这是一个示例,可以更好地向您展示。
enum RecType {
    Cons(i32, Box<RecType>),
    Nil,
}

现在,这将编译没有任何问题。
现在编译器知道要为RecType分配多少空间,因为我们知道RecType枚举中每个变体的大小。以下是我们如何使用此RecType递归存储数据。

use crate::RecType::{Cons, Nil};

fn main() {
    let data = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
}