智能指针
Rust 默认分配堆栈上的所有内容。 您可以通过将内容包装在像 Box 这样的智能指针中来将它们存储在堆上。 像 Vec 和 String 这样的类型隐式地帮助堆分配。 智能指针实现下表中列出的特征。 智能指针的这些特征将它们与普通结构区分开来 −
| Sr.No | 特征名称 | 封装 & 描述 |
|---|---|---|
| 1 | Deref | std::ops::Deref 用于不可变的取消引用操作,如 *v。 |
| 2 | Drop | std::ops::Drop 用于在值超出范围时运行某些代码。 这有时称为析构函数 |
在本章中,我们将了解Box智能指针。 我们还将学习如何创建像 Box 这样的自定义智能指针。
Box
Box 智能指针也称为 box,允许您在堆而不是堆栈上存储数据。 堆栈包含指向堆数据的指针。 除了将数据存储在堆上之外,Box 没有性能开销。
让我们看看如何使用盒子在堆上存储 i32 值。
fn main() {
let var_i32 = 5;
//stack
let b = Box::new(var_i32);
//heap
println!("b = {}", b);
}
输出
b = 5
为了访问变量指向的值,请使用取消引用。 * 用作解引用运算符。 让我们看看如何使用 Box 来取消引用。
fn main() {
let x = 5;
//value type variable
let y = Box::new(x);
//y points to a new value 5 in the heap
println!("{}",5==x);
println!("{}",5==*y);
//dereferencing y
}
变量 x 是一个值为 5 的值类型。因此,表达式 5==x 将返回 true。 变量 y 指向堆。 要访问堆中的值,我们需要使用 *y 取消引用。 *y 返回值 5。因此,表达式 5==*y 返回 true。
输出
true true
示例 - Deref 特征
标准库提供的 Deref 特征要求我们实现一个名为 deref 的方法,该方法借用 self 并返回对内部数据的引用。 下面的示例创建一个结构体MyBox,它是一个泛型类型。它实现了Deref特征。 此特征帮助我们使用 *y 访问由 y 包装的堆值。
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
// 带有静态方法的泛型结构 new
fn new(x:T)-> MyBox<T> {
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -> &T {
&self.0 //returns data
}
}
fn main() {
let x = 5;
let y = MyBox::new(x);
// 调用静态方法
println!("5==x is {}",5==x);
println!("5==*y is {}",5==*y);
// dereferencing y
println!("x==*y is {}",x==*y);
//dereferencing y
}
输出
5==x is true 5==*y is true x==*y is true
示例 - Drop 特性
Drop 特性包含 drop() 方法。 当实现此特征的结构超出范围时,将调用此方法。 在某些语言中,程序员每次使用完智能指针实例后都必须调用代码来释放内存或资源。 在 Rust 中,您可以使用 Drop 特性实现自动内存释放。
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
fn new(x:T)->MyBox<T>{
MyBox(x)
}
}
impl<T> Deref for MyBox<T> {
type Target = T;
fn deref(&self) -< &T {
&self.0
}
}
impl<T> Drop for MyBox<T>{
fn drop(&mut self){
println!("dropping MyBox object from memory ");
}
}
fn main() {
let x = 50;
MyBox::new(x);
MyBox::new("Hello");
}
在上面的示例中,当我们在堆中创建两个对象时,drop 方法将被调用两次。
dropping MyBox object from memory dropping MyBox object from memory