Rust语言 学习14 智能指针
  dBFTbkVLMBge 2023年11月02日 55 0

一、基本概念

Rust语言 学习14 智能指针_智能指针

Rust语言 学习14 智能指针_智能指针_02

Rust语言 学习14 智能指针_智能指针_03

Rust语言 学习14 智能指针_智能指针_04

Rust语言 学习14 智能指针_智能指针_05

Rust语言 学习14 智能指针_智能指针_06

二、使用Box指向Heap上的数据

Rust语言 学习14 智能指针_智能指针_07

Rust语言 学习14 智能指针_智能指针_08

使用Box<T>在heap上存储数据

fn main() {
   let b = Box::new(5);
   println!("b={}",b)
}

Rust语言 学习14 智能指针_智能指针_09

在作用域之外,会释放在stack上的指针 和 heap上的数据

Rust语言 学习14 智能指针_智能指针_10

Rust语言 学习14 智能指针_智能指针_11

Rust语言 学习14 智能指针_智能指针_12

Rust语言 学习14 智能指针_智能指针_13

use crate::List::{Cons,Nil};
enum List {
    Cons(i32,Box<List>),
    Nil,
}

fn main() {
   // 创建一个链表 使用Box智能指针
   let list = Cons(1,
                   Box::new(Cons(2,
                                 Box::new(Cons(3,
                                               Box::new(Nil))))));
}

三、Deref Trait

Rust语言 学习14 智能指针_智能指针_14

Rust语言 学习14 智能指针_智能指针_15

fn main() {
    let x = 5;
    let y = &6;
    assert_eq!(5,x);
    assert_eq!(6,*y);
}

Rust语言 学习14 智能指针_智能指针_16

fn main() {
    let x = 5;
    let y = Box::new(x);// y使用Box<T>的引用
    assert_eq!(5,x);
    assert_eq!(5,*y);
}

Rust语言 学习14 智能指针_智能指针_17

Rust语言 学习14 智能指针_智能指针_18

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;// 定义了deref trait的关联类型  关联类型是不同的泛型参数定义方式
    fn deref(&self) -> &Self::Target {
        &self.0 // 返回元组的第1个元素
    }
}
fn main() {
    let x = 5;
    let y = MyBox::new(x);
    //let y = Box::new(x);// y使用Box<T>的引用
    assert_eq!(5,x);
    assert_eq!(5,*y);
}

Rust语言 学习14 智能指针_智能指针_19

use std::ops::Deref;

fn hello(name :&str) {
    println!("Hello {}",name);
}
fn main() {
    let  m = MyBox::new(String::from("Rust"));
    // &m 也就是&MyBox<String>
    // deref 把它变成&String
    // deref 继续把它变成&str 也就是字符串切片类型
    hello(&m);
}
struct MyBox<T>(T); // 一个元素的元组
impl<T> MyBox<T> {
    fn new(x:T) -> MyBox<T> {
        MyBox(x)
    }
}

Rust语言 学习14 智能指针_智能指针_20

四、Drop Trait

Rust语言 学习14 智能指针_智能指针_21

struct CustomSmartPointer {
    data:String,
}

impl Drop for CustomSmartPointer {
    fn drop(&mut self) {
        println!("Dropping Pointer with data {}",self.data)
    }
}

fn main() {
    let c = CustomSmartPointer {
        data:String::from("my staff")
    };
    let d = CustomSmartPointer {
        data:String::from("other staff")
    };
    println!("smartPoiner created")
}

Rust语言 学习14 智能指针_智能指针_22

类似于c++的析构函数,或者go语言中的defer ,执行顺序和调用顺序相反

Rust语言 学习14 智能指针_智能指针_23

修改如下,调用下drop函数

Rust语言 学习14 智能指针_智能指针_24

通过运行结果发现,drop函数被提前执行了

Rust语言 学习14 智能指针_智能指针_25

五、Rc<T> 引用计数智能指针

Rust语言 学习14 智能指针_智能指针_26

Rust语言 学习14 智能指针_智能指针_27

Rust语言 学习14 智能指针_智能指针_28

use std::rc::Rc;
use crate::List::{Cons,Nil};

// 使用引用计数Rc指针
enum List {
    Cons(i32,Rc<List>),
    Nil
}

fn main() {
    // 定义链表a  5->10->Nil
    let a = Rc::new(Cons(5,
                 Rc::new(Cons(10,
                Rc::new(Nil)))));
    // a.clone() 是深度克隆操作  耗时比较长

    // 定义链表b 3->a
    let b = Cons(3,Rc::clone(&a)); // b不再获取a的所有权
    // 定义链表c 4->a
    let c = Cons(4,Rc::clone(&a));
}

Rust语言 学习14 智能指针_智能指针_29

Rust语言 学习14 智能指针_智能指针_30

六、RefCell<T>和内部可变性

Rust语言 学习14 智能指针_智能指针_31

Rust语言 学习14 智能指针_智能指针_32

Rust语言 学习14 智能指针_智能指针_33

Rust语言 学习14 智能指针_智能指针_34

Rust语言 学习14 智能指针_智能指针_35

Rust语言 学习14 智能指针_智能指针_36

Rust语言 学习14 智能指针_智能指针_37

Rust语言 学习14 智能指针_智能指针_38

// 引用的内部可变性demo
pub trait Messenger {
    fn send(&self,msg:&str); // 接收self不可变引用作为参数
}

// 泛型
pub struct LimitTracker<'a,T: 'a + Messenger> {
    messenger : &'a T,
    value:usize,
    max:usize,
}

// 实现trait
impl <'a,T> LimitTracker<'a,T>
    where
        T:Messenger,
{
    // 定义new方法
    pub fn new(messenger: &T,max:usize) -> LimitTracker<T> {
        LimitTracker{
            messenger,
            value:0,
            max,
        }
    }
    // 定义set_value方法
    pub fn set_value(&mut self,value:usize) {
        self.value = value;
        let percentage = self.value as f64 / self.max as f64;
        if percentage >= 1.0 {
            self.messenger.send("Error , too big");
        } else if percentage >=0.9 {
            self.messenger.send("warn used up 90%");
        } else if percentage >=0.75 {
            self.messenger.send("warn used up 75%")
        }
    }
}

// 单元测试代码 验证
#[cfg(test)]
mod tests {
    use super::*;
    use std::cell::RefCell;
    struct MockMessenger {
        send_messages : RefCell<Vec<String>>,
    }
    // 实现new方法
    impl MockMessenger {
        fn new() -> MockMessenger {
            MockMessenger {
                send_messages: RefCell::new(vec![]),
            }
        }
    }
    // 实现send方法
    impl Messenger for MockMessenger {
        fn send(&self,message: &str)  {
            // borrow mut获取可变引用
            self.send_messages.borrow_mut().push(String::from(message));
        }
    }

    // 测试代码
    #[test]
    fn it_sends_75_percent_warn_message() {
        let mock_messenger = MockMessenger::new();
        let mut limit_tracker = LimitTracker::new(&mock_messenger,100);

        limit_tracker.set_value(80);
        // borrow获取不可变引用
        assert_eq!(mock_messenger.send_messages.borrow().len(),1);
    }
}

Rust语言 学习14 智能指针_智能指针_39

Rust语言 学习14 智能指针_智能指针_40

Rust语言 学习14 智能指针_智能指针_41

Rust语言 学习14 智能指针_智能指针_42

Rust语言 学习14 智能指针_智能指针_43

Rust语言 学习14 智能指针_智能指针_44

运行结果为

Rust语言 学习14 智能指针_智能指针_45

Rust语言 学习14 智能指针_智能指针_46

七、循环引用导致内存泄漏

Rust语言 学习14 智能指针_智能指针_47

use std::cell::RefCell;
use std::rc::Rc;
use crate::List::{Cons, Nil};

// 定义一个list
#[derive(Debug)]
enum List {
    Cons(i32,RefCell<Rc<List>>),
    Nil,
}

// 具体方法
impl List {
    fn tail(&self) -> Option<&RefCell<Rc<List>>> {
        match self {
            Cons(_,item) => Some(item),
            Nil => None,
        }
    }
}


fn main() {
    // 定义链表a  5->Nil
    let a = Rc::new(Cons(5,RefCell::new(Rc::new(Nil))));

    println!("a initial rc count = {}",Rc::strong_count(&a));
    println!("a next item = {:?}",a.tail());

    // 定义链表b  10->a
    let b = Rc::new(Cons(10,RefCell::new(Rc::clone(&a))));
    // 分别打印a和b的强引用数量
    println!("a rc count after b creation = {}",Rc::strong_count(&a));
    println!("b initial rc count = {}",Rc::strong_count(&b));
    // 打印b链表的尾部元素
    println!("b next item = {:?}",b.tail());
    // 再打印a的链表尾部
    if let Some(link) = a.tail() {
        // 把a链表的Nil ,改成b链表 形成循环链表
        *link.borrow_mut() = Rc::clone(&b);
    }

    // 然后再分别打印b和a的强引用数量
    println!("b rc count after changing a = {}",Rc::strong_count(&b));
    println!("a rc count after changing a = {}",Rc::strong_count(&a));
}

Rust语言 学习14 智能指针_智能指针_48

Rust语言 学习14 智能指针_智能指针_49

Rust语言 学习14 智能指针_智能指针_50

Rust语言 学习14 智能指针_智能指针_51


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

dBFTbkVLMBge