📜  Rust——智能指针的概念

📅  最后修改于: 2022-05-13 01:55:19.077000             🧑  作者: Mango

Rust——智能指针的概念

指针基本上是存储另一个变量地址的变量。虽然智能指针是行为类似于传统指针的数据类型,但具有其他功能,例如自动内存管理或边界检查。

智能指针与普通指针的不同之处在于:-

  • 它们是结构体,包含额外的元数据和功能。
  • 他们不借用数据,而是拥有数据。

是什么让智能指针与结构不同:-

  • 它们实现了DerefDrop特性。

Deref trait 允许智能指针结构的实例表现得像一个引用,这样处理指针的代码也可以处理智能指针。

Drop trait 允许我们自定义当智能指针的实例超出范围时应该运行的代码。



一些智能指针是:-

  • Box 在堆上分配值
  • Rc 一种支持多重所有权的引用计数类型

盒子

Box 允许我们将数据存储在堆中,这与 Rust 存储为堆栈的默认方案相反。

Box 主要用于:

  • 用于为变量动态分配内存。
  • 当有大量数据需要转移所有权时,我们不希望它们被复制。

让我们创建一个盒子来在堆中存储 i32 值

Rust
fn main() {
    let num = Box::new(4);
    println!("num = {}", num);
}


Rust
enum List {
    Cons(i32, List),
    Nil,
}
use crate::List::{Cons, Nil};
  
fn main() {
    let list = Cons(1, Cons(2, Cons(3, Nil)));
}


Rust
#[derive(Debug)]
enum List {
    Cons(i32, Box),
    Nil,
}
  
use crate::List::{Cons, Nil};
  
fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    println!("{:?}",list)
}


Rust
struct CustomPointer(T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}


Rust
struct CustomPointer(T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}
//implementing deref trait
use std::ops::Deref;
impl Deref for CustomPointer {
    type Target = T;
      
    fn deref(&self) -> &Self::Target {
        &self.0
    }
      
}
fn main() {
    let x = 5;
    let y = CustomPointer::new(x);
  
    println!("{}",x==5);
    println!("{}",*y==5);
}


Rust
// defining custom smart pointer
struct CustomPointer (T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}
use std::ops::Deref;
  
// for implementing deref trait
impl Deref for CustomPointer {
    type Target = T;
      
    fn deref(&self) -> &Self::Target {
        &self.0
    }
      
}
// for implementing drop trait
impl  Drop for CustomPointer {
    fn drop(&mut self) {
        println!("Dropping CustomtPointer with data");
    }
}
fn main() {
    let x = 5;
    let y = CustomPointer::new(x);
  
    println!("{}",x==5);
    println!("{}",*y==5);
}


输出

num = 4

使用 Box 作为递归类型

我们将使用 cons list 创建一个值列表。 cons list 取值第一个是当前值,另一个是下一个值,它执行对 cons函数的递归调用以生成一个列表,其中递归调用的基本条件是 Nil。



enum List {
    Cons(i32, List),
    Nil,
}
use crate::List::{Cons, Nil};
  
fn main() {
    let list = Cons(1, Cons(2, Cons(3, Nil)));
}

它不会编译,因为在编译之前无法确定 List 变量大小。

输出:

 rustc -o main main.rs
error[E0072]: recursive type `List` has infinite size
 --> main.rs:1:1
  |
1 | enum List {
  | ^^^^^^^^^ recursive type has infinite size
2 |     Cons(i32, List),
  |               ---- recursive without indirection
  |
  = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable

error[E0391]: cycle detected when processing `List`
 --> main.rs:1:1
  |
1 | enum List {
  | ^^^^^^^^^
  |
  = note: ...which again requires processing `List`, completing the cycle
  = note: cycle used when computing dropck types for `Canonical { max_universe: U0, variables: [], value: ParamEnvAnd { param_env: ParamEnv { caller_bounds: [], reveal: UserFacing, def_id: None }, value: List } }`

有一个错误告诉 List 具有无限大小,因为编译器在编译期间无法确定 List 的大小。所以我们将使用指向列表的指针而不是列表本身来克服这个错误。由于指针的大小是固定的,与它指向的数据类型无关,因此编译器可以在编译期间确定其大小。让我们看看这个使用 Box 的实现

#[derive(Debug)]
enum List {
    Cons(i32, Box),
    Nil,
}
  
use crate::List::{Cons, Nil};
  
fn main() {
    let list = Cons(1, Box::new(Cons(2, Box::new(Cons(3, Box::new(Nil))))));
    println!("{:?}",list)
}

输出:

Cons(1, Cons(2, Cons(3, Nil)))

定义我们自己的智能指针:

struct CustomPointer(T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}

在这里,我们将自定义智能指针定义为一个具有一个值的元组结构。我们定义了一个新方法,它在智能指针被实例化时被调用,它返回一个自定义的智能指针。

在我们的自定义智能指针上使用取消引用特征:

就像普通的指针一样,我们可以通过使用'*'运算符来获取盒子的值。

struct CustomPointer(T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}
//implementing deref trait
use std::ops::Deref;
impl Deref for CustomPointer {
    type Target = T;
      
    fn deref(&self) -> &Self::Target {
        &self.0
    }
      
}
fn main() {
    let x = 5;
    let y = CustomPointer::new(x);
  
    println!("{}",x==5);
    println!("{}",*y==5);
}

输出:

true
true

在我们的智能指针上使用 Drop trait:

每当智能指针的实例超出范围时,就会调用 drop函数。

// defining custom smart pointer
struct CustomPointer (T);
  
impl CustomPointer {
    fn new(x: T) -> CustomPointer {
        CustomPointer(x)
    }
}
use std::ops::Deref;
  
// for implementing deref trait
impl Deref for CustomPointer {
    type Target = T;
      
    fn deref(&self) -> &Self::Target {
        &self.0
    }
      
}
// for implementing drop trait
impl  Drop for CustomPointer {
    fn drop(&mut self) {
        println!("Dropping CustomtPointer with data");
    }
}
fn main() {
    let x = 5;
    let y = CustomPointer::new(x);
  
    println!("{}",x==5);
    println!("{}",*y==5);
}

输出:

true
true
Dropping CustomtPointer with data