Rust引用和借用

213 阅读2分钟

1.为什么使用引用

为什么需要引用呢,当你想用某个变量,但是并不想得到他的所有权的时候,可以用引用。

2.如何使用

  • 参考的类型是&String,而不是String
  • &符号就表示引用:允许你引用某些值而不取得其所有权

图片.png

fn main(){
    let s1 = String::from("hello");
    let get_len = cal_len(&s1);
    println!("{} 字符串的长度是:{}",s1,get_len);
}

fn cal_len(s: &String) -> usize {
    s.len()
}

把引用作为函数参数的这个行为叫借用

3.如何通过引用修改变量的原始值

现在如果想要在函数中修改引用的值,还是不可以的,因为现在这个引用还是不可变的。

我们需要这样

fn main(){
    let mut s1 = String::from("hello");
    let get_len = cal_len(&mut s1);
    println!("{} 字符串的长度是:{}",s1,get_len);
}

fn cal_len(s: &mut String) -> usize {
    s.push_str(",hdat");
    s.len()
}

让变量和引用都是可变的,现在,就可以通过引用修改到变量的原始值了。

4.可变引用需要注意

  • 可变引用有一个重要的限制:在特定的作用域内,对某一块数据,只能有一个可变的引用。
    • 这样可以在编译时防止数据竞争。
  • 会发生数据竞争的三种行为:
    • 两个或多个指针同时访问同一个数据
    • 至少有一个指针用于写入数据
    • 没有使用使用任何机制来同步多数据的访问

但是,如果就想使用多个可变引用,也是可以的,可以通过创建新的作用域来实现

fn main() {
    let mut s = String::from("hello");
    {
        let s1 = &mut s;
    }
    let s2 = &mut s;
}

一旦允许多个可变引用存在,那就不能同时拥有一个不可变的引用

多个不变的引用是可以的,但是多个可变的引用中不能存在一个不可变的引用

5.悬空引用

  • 悬空指针: 一个指针引用了内存中的某个地址,然而这块内存可能已经释放并分配给其他人使用了。
  • rust中,编译器可以保证引用永远都不是悬空引用。
fn main() {
    let r = dangle();
}

// 因为出了这个函数,s就被释放了,所以返回的引用指向的是一块被释放的存储空间
fn dangle() -> &String {
    let s = String::from("hello");
    &s
}

这个时候,编译的时候就会报错,防止这种错误的发生。

6.引用的规则

  • 在任何时刻,只能满足以下一个条件:
    • 一个可变的引用
    • 多个不可变的引用
  • 引用必须一直有效,别让其所指向的位置被释放了