Rust智能指针简介

Rust智能指针简介

说起智能指针,还得看C++,智能指针的概念就来自于C++,Rust中的智能指针用处和用法其实与C++类似。

应当首先认识到,在 Rust 中,普通引用和智能指针的一个区别是引用是一类只借用数据的指针;相反,在大部分情况下,智能指针 拥有 它们指向的数据。这里智能指针和引用相比较更多的保证了数据安全性,而不是像C++一样仅仅是实现堆上数据的RAII这么简单。

常在以下场景使用智能指针:

  • 当有一个在编译时未知大小的类型,而又想要在需要确切大小的上下文中使用这个类型值的时候
  • 当有大量数据并希望在确保数据不被拷贝的情况下转移所有权的时候
  • 当希望拥有一个值并只关心它的类型是否实现了特定 trait 而不是其具体类型的时候

智能指针对资源的管理其实还是类似于RAII那一套,在Rust里是这么描述的:

智能指针区别于常规结构体的显著特性在于其实现了 DerefDrop trait。Deref trait 允许智能指针结构体实例表现的像引用一样,这样就可以编写既用于引用、又用于智能指针的代码。Drop trait 允许我们自定义当智能指针离开作用域时运行的代码。

Deref trait

实现 Deref trait 允许我们重载 解引用运算符dereference operator*。通过这种方式实现 Deref trait 的智能指针可以被当作常规引用来对待,可以编写操作引用的代码并用于智能指针。

use std::ops::Deref;
struct MyBox<T>(T);

impl<T> MyBox<T> {
    fn new(x: T) -> MyBox<T> {
        MyBox(x)
    }
}
// 实现deref trait
impl<T> Deref for MyBox<T> {
    type Target = T;

    fn deref(&self) -> &T {
        &self.0
    }
}

fn main() {
    let x = 5;
    let y = MyBox::new(x);

    assert_eq!(5, x);
    //实现了deref trait,能成功解引用
    assert_eq!(5, *y);
}



最后再说一说,解引用强制转换deref coercions),这其实就是Rust 编译器实的一个类似语法糖的东西,可以让我们再在函数或方法传参上少写一些乱七八糟的符号。

//几个例子
fn hello(name: &str) {
    println!("Hello, {}!", name);
}
fn main() {
	let m = MyBox::new(String::from("Rust"));
    hello(&m);
}
//该函数接收一个&str参数,传入一个咱之前实现的MyBox引用居然可以
//原因就归功于编译器帮我们实现的解引用强制转换,转换过程大致如下
//&MyBox   ->    &String    ->     &str
//如果编译器没有这个功能那么就要这么写(瞬间变丑):
let m = MyBox::new(String::from("Rust"));
hello(&(*m)[..]);

Drop Trait

Drop Trait功能和C++的析构函数如出一辙,不解释了,就是释放资源的。需要记住的是Rust会自己去在合适的时机调用drop(),所以其不允许用户自己调用drop()方法,实在想要提前释放资源,可以使用std::mem::drop.

Box< T >

Box感觉和unique_ptr比较类似,就一个单纯的用于指向堆上数据的智能指针,没有过多的特殊功能。不过由于Rust语言安全的特性,裸指针不像C/C++一样作为一等公民,所以Box还承担了一个定义未知大小类型的功能。


enum List {
    Cons(i32, Box<List>),
    Nil,
}

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

fn main() {
    //主要功能1,数据5位于堆上
    let p = Box<i32>::new(5);
    //主要功能2,若不使用Box,lsit大小是未知的
    let list = Cons(1,
        Box::new(Cons(2,
            Box::new(Cons(3,
                Box::new(Nil))))));
}

Rc< T >

类似上面的Box,Rc好比C++的shared_ptr,多智能指针共享一个资源,自然而然会涉及到引用计数问题,例如循环引用,与C++的shared_ptr一致,此处从略

RefCell < T >

该智能指针类似Box,但是他通过unsafe来规避的Rust的引用借用规则,是Rust提供的处理类似停机问题的无法在编译期进行代码检查的手段。

这里涉及了内部可变性等一些RefCell较复杂的原理,由于是简介这里不介绍啦。

你可能感兴趣的:(Rust学习,rust,开发语言,后端)