• 【Rust】快速教程——闭包与生命周期


    前言

    你怎么向天生的瞎子说清颜色?怎么用手势向天生的聋子描述声音? 鲜花就在眼前,雷鸣就在头顶,对他们来说却都毫无意义 眼睛看不到,鼻子可以嗅闻花香,耳朵听不见,手指可以触碰窗纸的震动。 犯错的可能是描述者,而不是瞎子和聋子:你明知道他们无法领会颜色与声音,为什么非要生硬地灌输呢?换一种方法,用他们能理解的方式,同样能传递信息。——《拔魔》


             \;\\\;\\\;

    借用

    借用borrow很像是引用reference,也就是地址。但是有限制,不能借用多次,即不能借用完了还当借用在自己这

    fn main() {
        let mut s = String::from("hello");
    
        let a = &mut s;
        let b = &mut s; //不安全,报错,怎么能把可变的借用给两个ID
    
        println!("{}, {}", a, b);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

             \;\\\;\\\;

    生命周期

    fn main() {
        // let r;
        // {
        //     let a = 5;
        //     r = &a;
        // }
        // println!("r={}", r); //报错,因为a被回收了
        
    
        let r;
        {
            let a = 5;
            r=a; //这样就没错了,因为这里是拷贝了一份
        }
        println!("r={}",r);
    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    在这里插入图片描述

    fn main() {
        let s=max("hola","hello");
        println!("s={}",s);
    }
    
    
    //fn max(x:&str,y:&str)->&str{ //报错,因为没指明两个参数的作用域
    fn max<'a>(x:&'a str,y:&'a str)->&'a str{
        if x.len() > y.len(){
            x
        }
        else{
            y
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    在这里插入图片描述

    'a 进行声明周期标注,比如 'static 就是标注为全局静态。

    fn main() {
        let a=String::from("hola");
        {
            let b=String::from("hello");
        }
        println!("max is {}",max(&a,&b)); //报错,b被回收了
    }
    
    fn max<'a>(x:&'a str,y:&'a str)->&'a str{
        if x.len() > y.len(){
            x
        }
        else{
            y
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    #[derive(Debug)]
    struct MyPack<'a> {
        part: &'a str, 
    //    tally:&'b str,
    }
    
    fn main() {
        let i;
        {
            let a: String = String::from("test... i. t.."); //待分割的字符串
    
            let b: &str = a.split(".").next().expect("not find .");
    
            i = MyPack { part: b };
        }
        println!("part : {:?},", i); //错误,因为b被释放了
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

             \;\\\;\\\;

    #[derive(Debug)]
    struct Foo;
    
    impl Foo{
        //传入可变借用,传出不可变借用(没有mut)
        //就是把可变借用转化为了不可变借用
        fn exec(&mut self)->&Self{
            &*self  //取星号是为了和传入的&抵消,不然&self就变成了地址的地址了
        }
        fn run(&self){
            println!("2");
        }
    }
    
    
    fn main(){
        let mut f : Foo = Foo;//f是可变的
        f.run(); //f是可变的
       
        let a : &Foo = f.exec(); //a是可变的,f借用给了a,所以下面f调用就出错了
       // println!("{:?}",a); //Foo
        f.run(); //只要后面有打印,就报错???
        //println!("{:?}",a); //Foo f.run()后面没有这句打印,就没错了
    
        println!("---------------------");
        {
            let mut b : Foo = Foo;//b是可变的
            {
                b.run();
                let c : &Foo = b.exec(); //c也是不可变的
                {
                    //b.exec();
                    //b.run();
                    //c.exec();
                    c.run(); //不可变的c可以调用run
                }
                println!("{:?}",c);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40

    在这里插入图片描述

    #[derive(Debug)]
    struct Foo;
    
    impl Foo{
        fn exec(&mut self)->&mut Self{
            &mut *self 
        }
        fn run(&self){
            println!("2");
        }
    }
    
    
    fn main(){
        {
            let mut b : Foo = Foo;//b是可变的
            {
                b.run();
                let c : &mut Foo = b.exec(); //c是可变的
                {
                    //b.exec();
                    //b.run();
                    c.exec();
                    c.run(); 
                }
                println!("{:?}",c);
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    在这里插入图片描述

             \;\\\;\\\;

    闭包

    就是lambda表达式,也是匿名函数

    fn main(){
        let x:f64=100f64;
        let add = |y:f64| x+y  ;     //闭包
        let sub = |y| ->i64 { (x-y) as i64 };
        let one = ||1;
    
        println!("add : {}",add(20f64));
        println!("sub : {}",sub(20f64));
        println!("one : {}",one());
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

             \;\\\;\\\;

  • 相关阅读:
    Vue基础(八)——路由
    射频微波芯片设计3:射频微波芯片设计基础知识
    机器学习概念(一)
    【面试刷题】——Linux基础命令
    JAVA微信小程序商城源码:带完整后台运行版
    前端实现分页效果
    PHP语言之正则表达式
    ssm基于Java web 的人人影视网站管理系统 毕业设计-附源码290915
    使用Token管理用户session
    【面试题-Vue】常见问题二、组件类
  • 原文地址:https://blog.csdn.net/weixin_41374099/article/details/134475293