Rust 智能指针
Rust默认将所有东西分配在栈上。您可以通过将它们包装在智能指针中来将东西存储在堆上,比如 Box。像 Vec 和 String 这样的类型会隐式帮助堆分配。智能指针实现了下表中列出的特质。这些智能指针的特质使它们与普通结构体不同 –
序号 | 特质名称 | 包 & 描述 |
---|---|---|
1 | Deref | std::ops::Deref 用于进行不可变解引用操作,如 *v 。 |
2 | Drop | std::ops::Drop 当一个值超出作用域时运行一些代码。有时被称为析构函数。 |
在本章中,我们将学习关于 Box 智能指针。我们还将学习如何创建类似于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的方法,该方法借用self并返回内部数据的引用。以下示例创建了一个结构体MyBox,它是一个通用类型。它实现了Deref特征。该特征帮助我们通过*y来访问被y包裹的堆值。
use std::ops::Deref;
struct MyBox<T>(T);
impl<T> MyBox<T> {
// Generic structure with static method 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);
// calling static method
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 trait
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