zoukankan      html  css  js  c++  java
  • Rust 2):引用&借用(zz)

     

    引用&借用(References&Borrowing

    如上所示,Owership让我们改变一个变量的值变得“复杂”,那能否像其他编程语言那样随意改变变量的值呢?答案是有的。

    所有权系统允许我们通过“Borrowing”的方式达到这个目的。这个机制非常像其他编程语言中的“读写锁”,即同一时刻,只能拥有一个“写锁”,或只能拥有多个“读锁”,不允许“写锁”和“读锁”在同一时刻同时出现。当然这也是数据读写过程中保障一致性的典型做法。只不过Rust是在编译中完成这个(Borrowing)检查的,而不是在运行时,这也就是为什么其他语言程序在运行过程中,容易出现死锁或者野指针的问题。

    通过&符号完成Borrowing:

    fn main() {

       let x: Vec<i32> = vec!(1i32, 2, 3);

       let y = &x;

       println!("x={:?}, y={:?}", x, y);

    }

    Borrowing(&x)并不会发生所有权moved,所以println可以同时访问x和y。 通过引用,就可以对普通类型完成修改。

    fn main() {

       let mut x: i32 = 100;

        {

           let y: &mut i32 = &mut x;

           *y += 2;

        }

        println!("{}", x);

    }

    借用与引用的区别

    借用与引用是一种相辅相成的关系,若B是对A的引用,也可称之为B借用了A。

    很相近对吧,但是借用一词本意为要归还。所以在Rust用引用时,一定要注意应该在何处何时正确的“归回”借用/引用。 最后面的“高级”小节会详细举例。

    规则

    1. 同一时刻,最多只有一个可变借用(&mut T),或者2。
    2. 同一时刻,可有0个或多个不可变借用(&T)但不能有任何可变借用。
    3. 借用在离开作用域后释放。
    4. 在可变借用释放前不可访问源变量。

    可变性

    Borrowing也分“不可变借用”(默认,&T)和“可变借用”(&mut T)。

    顾名思义,“不可变借用”是只读的,不可更新被引用的内容。

    fn main() {

       let x: Vec<i32> = vec!(1i32, 2, 3);

     

       //可同时有多个不可变借用

       let y = &x;

       let z = &x;

       let m = &x;

     

       //ok

       println!("{:?}, {:?}, {:?}, {:?}", x, y, z, m);

    }

    再次强调下,同一时刻只能有一个可变借用(&mut T),且被借用的变量本身必须有可变性:

    fn main() {

       //源变量x可变性

       let mut x: Vec<i32> = vec!(1i32, 2, 3);

     

       //只能有一个可变借用

       let y = &mut x;

       // let z = &mut x; //错误

       y.push(100);

     

       //ok

       println!("{:?}", y);

     

       //错误,可变借用未释放,源变量不可访问

       // println!("{:?}", x);

    } //y在此处销毁

    高级例子

    下面的复杂例子,进行了详细的注释,即使看不懂也没关系,可以在完成Lifetimes(生命周期)的学习后再仔细思考本例子。

    fn main() {

       let mut x: Vec<i32> = vec!(1i32, 2, 3);

     

       //更新数组

       //push中对数组进行了可变借用,并在push函数退出时销毁这个借用

       x.push(10);

     

        {

           //可变借用1

            let mut y = &mut x;

           y.push(100);

     

           //可变借用2,注意:此处是对y的借用,不可再对x进行借用,

           //因为y在此时依然存活。

           let z = &mut y;

           z.push(1000);

     

           println!("{:?}", z); //打印: [1, 2, 3, 10, 100, 1000]

        } //yz在此处被销毁,并释放借用。

     

       //访问x正常

        println!("{:?}", x); //打印: [1, 2, 3, 10, 100, 1000]

    }

    总结

    1. 借用不改变内存的所有者(Owner),借用只是对源内存的临时引用。
    2. 在借用周期内,借用方可以读写这块内存,所有者被禁止读写内存;且所有者保证在有“借用”存在的情况下,不会释放或转移内存。
    3. 失去所有权的变量不可以被借用(访问)。
    4. 在租借期内,内存所有者保证不会释放/转移/可变租借这块内存,但如果是在非可变租借的情况下,所有者是允许继续非可变租借出去的。
    5. 借用周期满后,所有者收回读写权限
    6. 借用周期小于被借用者(所有者)的生命周期。

    备注:   借用周期,指的是借用的有效时间段。

    上一篇: 所有权下一篇: 生命周期

     

     

     

  • 相关阅读:
    转:Metronic – 超赞!基于 Bootstrap 的响应式后台管理模板
    [km] 如何判断一个直播系统是否使用的是RTMP
    xshell5.0实现中键复制
    [转] 腾讯云直播OBS推流教程
    eclipse格式化代码快捷键失效
    JAVA注解@Interface基础知识
    MySQL按中文拼音排序
    Navicat连不上mysql8
    MySQL重置root密码
    CentOS7防火墙之firewalld
  • 原文地址:https://www.cnblogs.com/cx2016/p/12926209.html
Copyright © 2011-2022 走看看