借用&引用

上一节我们已经见识过了 所有权的威力,也看到了所有权所带来的编写代码的不方便;那有没有什么方法可以缓解这个痛苦?

借用就是为了 规避(这里并不严谨)所有权规则的限制 而诞生的,借用可以达到的作用就是 可以不需要获得所有权,但是也可以拿到变量

引用

引用一般有两种形式

  • 共享引用
  • 可变引用

但无论哪种引用 本身是一个 RUST实现的指针类型

Screenshot

fn main(){
    let mut vec = Vec::from([0;10]);
    let ref vec_ref = vec;
    println!("{:?}",vec_ref);
    vec.push(1);
    let  vec_ref = &vec;
    println!("{:?}",vec_ref);
    println!("{:?}",vec);
}

引用的约束:

  • 使用引用变量区间,不允许超过被引用的变量的时间 (回答为什么)

共享引用

引用默认是共享引用 共享引用的含义就是:

  • 该引用不拥有该变量的所有权
  • 不能通过引用修改引用的变量
  • 共享引用可以有多份副本

实验1: 共享引用不拥有所有权,共享引用销毁 引用的变量不销毁

#[derive(Debug)]
struct Apple;

fn borrow_apple(apple: &Apple) {
    println!("borrow can access variable{:?}", *apple);
}

fn main() {
    let apple:Apple = Apple;
    borrow_apple(&apple);
    println!(" apple is alive {:?}",apple);
}

实验2: 共享引用不能修改引用的变量

#[derive(Debug)]
struct Apple{
    size: i32,
}

fn borrow_apple(apple: &Apple) {
    println!("borrow can access variable{:?}", *apple);
    apple.size=20; 
}

fn main() {
    let apple:Apple = Apple {size:10};
    borrow_apple(&apple);
    println!(" apple is alive {:?}",apple);
}

实验3: 共享引用实现了Copy 特征,可以被复制多份

#[derive(Debug)]
struct Apple;

fn borrow_apple(apple: &Apple) {
    println!("borrow can access variable{:?}", *apple);
}

fn main() {
    let apple:Apple = Apple;
    let apple_ref1 = &apple;
    let apple_ref2 = apple_ref1;

    borrow_apple(&apple_ref2);
    borrow_apple(&apple_ref1);

    println!(" apple is alive {:?}",apple);
}

共享引用的约束

基于共享引用的特点,RUST 对共享引用也提出了约束

  • 使用共享引用变量期间,被引用的变量不允许修改 (回答为什么)
  • 使用共享引用期间,不允许有 可变引用再使用 (讲完下一节再看)

实验1: 使用共享引用变量期间,被引用的变量不允许修改

#[derive(Debug)]
struct Apple{
    size: i32,
}

fn borrow_apple(apple: &Apple) {
    println!("borrow can access variable{:?}", *apple);
}

fn main() {
    let mut apple:Apple = Apple {size:10};
    let apple_ref = &apple;
    borrow_apple(&apple_ref);
    apple.size=20;

    //let apple_ref = &apple;
    borrow_apple(&apple_ref);

    println!(" apple is alive {:?}",apple);
}

可变(独占)引用

其实引用有点类似于一个读写锁的实现。读锁可以被很多人使用(读锁占用以后,写锁也被锁), 写锁只允许一个人持有(持有写锁以后,读锁也被锁)

如果说共享引用隐含读锁的含义,那么独占(可变)引用则隐含有写锁的含义

可变引用的含义就是:

  • 该引用不拥有该变量的所有权
  • 可以通过引用修改引用的变量
  • 独占引用不能有多个副本

可变引用的约束就是:

  • 再可变引用生效期间,不允许其他人再修改变量
  • 一个变量可以有可变引用,该变量也必须是可变的 (思考为什么)

实验1: 独占引用不拥有所有权,引用销毁 引用的变量不销毁

#[derive(Debug)]
struct Apple;

fn borrow_apple(apple: &mut Apple) {
    println!("borrow can access variable{:?}", *apple);
}

fn main() {
    let mut apple:Apple = Apple;
    borrow_apple(&mut apple);
    println!(" apple is alive {:?}",apple);
}

实验2: 可以通过独占引用修改引用的变量

#[derive(Debug)]
struct Apple{
    size: i32,
}

fn borrow_apple(apple: &mut Apple) {
    apple.size=20; 
    println!("mut borrow can modify variable{:?}", apple);
}

fn main() {
    let mut apple:Apple = Apple {size:10};
    println!(" apple original is  {:?}",apple);
    borrow_apple(&mut apple);
    println!(" apple is modified {:?}",apple);
}

实验3: 独占引用没有实现Copy特征,= 会触发 引用变量所有权移动

#[derive(Debug)]
struct Apple;

fn borrow_apple(apple: &Apple) {
    println!("borrow can access variable{:?}", *apple);
}

fn main() {
    let mut apple:Apple = Apple;
    let apple_ref1: &mut Apple = &mut apple;
    let apple_ref2 = apple_ref1;

    borrow_apple(&apple_ref2);
    borrow_apple(&apple_ref1);

    println!(" apple is alive {:?}",apple);
}

实验4: 使用独占引用变量期间,变量不允许修改

#[derive(Debug)]
struct Apple{
    size: i32,
}

fn borrow_apple(apple: &mut Apple) {
    apple.size=20; 
    println!("mut borrow can modify variable{:?}", apple);
}

fn main() {
    let mut apple:Apple = Apple {size:10};
    println!(" apple original is  {:?}",apple);
    let apple_ref = &mut apple;
    apple.size = 30;
    borrow_apple(apple_ref);
    println!(" apple is modified {:?}",apple);
}

引用的应用

引用再RUST 中无处不再,需要结合所有权一起理解 下面是一个方法中的引用使用

enum AppleColor {
    Red,
    Green,
}

#[derive(Debug)]
struct Apple{
    size: i32,
    color:AppleColor,
}

impl Apple {
    fn replace_apple(self) -> Apple {
        if (self.size < 20) {
            Apple{size: 20, color:self.color}
        } else {
            self
        }
    }

    fn show_apple(&self) {
        println!("{:?}",self);
    }

    fn change_color(&mut self, color: AppleColor ) {
        self.color = color;
    }
}

fn main() {
    let mut apple:Apple = Apple {size:10};
    println!(" apple original is  {:?}",apple);
    let apple_ref = &mut apple;
    apple.size = 30;
    borrow_apple(apple_ref);
    println!(" apple is modified {:?}",apple);
}

总结

所有权规定了一个变量和变量的值该什么时候销毁, 可变变量规定了一个变量是否可变;

所有权实际操作中 会让编码变得困难,引用的出现,再保证变量所有权合法访问基础上 解放了部分变量的访问