

概述
指针是一个通用的编程概念,指的是在内存中包含一个地址的变量。在Rust中,除了普通的指针之外,我们还有智能 指针。智能 指针是一种数据结构,它不仅可以作为一个指针,而且还具有额外的元数据和能力。盒式 指针是Rust中智能指针的一种。
盒式指针
盒式指针允许你在堆上而不是在栈上存储数据。留在堆栈上的是指向堆 数据的指针。
let ptr = Box::new(25);
除了将数据存储在堆以外的堆上,Box没有任何其他功能。我们在以下情况下使用Box
- 当你有一个在编译时无法知道大小的类型,而你想在一个需要精确大小的上下文中使用该类型的值时
- 如果你有大量的数据,而你想转移所有权,但要确保在转移时数据不会被复制。
- 当你想拥有一个值,而你只关心它是一个实现了特定特征的类型,而不是一个特定的类型时
使用盒子类型来存储数据
正如我们上面所讨论的,盒子 类型是用来在堆上而不是在栈上存储数据的。指向堆上数据的指针确实被存储在堆上。这里有一个例子来更好地解释它。
fn main() {
let ptr = Box::new("hello");
println!("The pointer points to data : {}", ptr);
}
在上面的例子中,有一个变量ptr存储了一个指向字符串 "hello "的盒子 指针。字符串 "hello "在堆上,盒子指针 **ptr**是在堆栈上。
The pointer points to data : hello
ptr变量拥有盒子的指针,因此所有权的规则也适用于它。随着主方法的结束,ptr盒式指针所指向的内存将被释放,堆栈上的盒式指针也将被释放。
使用盒式指针的递归类型
在任何编程语言中,编译器需要知道任何数据类型所占用的空间。这对Rust编译器来说也是一样的,但在递归 类型的情况下,这就相当困难了。递归 类型是一种类型,其中的值可以作为自身的一部分拥有另一个相同类型的值。所以编译器不知道在编译时要为这种数据类型分配多少内存。这里有一个例子可以更好地解释它。
enum RecType {
Cons(i32, Rectype),
Nil,
}
这里,RecType是一个递归枚举,它有一个变体,与一个元组 *(i32,RecType)*相关。这个元组包含一个i32值和一个相同类型的值,即RecType。所以,在这种情况下,编译器在编译时为 RecType分配空间变得很困难。
为了克服这个问题,我们可以使用盒式 指针。由于我们可以在编译时知道 盒式指针所需的空间,我们可以在元组内使用一个盒式 指针,它将指向一个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))))));
}
以上就是关于Rust中盒式指针的全部内容。