Skip to content

第五节、引用和借用

引用和借用

先介绍一下References (引用)和 Borrowing(借用)的概念

引用类似C语言的指针,使用&符号。不同的是指针是可以完全使用和修改内容的。引用只能获取信息,不具有所有权,不能修改。

     fn main() {
           let s1 = String::from("hello");

           let len = calculate_length(&s1);
           println!("The length of '{}' is {}.", s1, len);
    }

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

上面的代码是获取 s1的长度,这个是可以的。

     fn main() {
           let s = String::from("hello");
           change(&s);
      }
      fn change(some_string: &String) {
          some_string.push_str(", world");
      }

例子2是会报错的

我们看一下 s和s1的 引用图,

2581644909158_.pic.jpg

可变的引用

我们通过一些小的调整来修改借用( borrowed)的值,而这些小调整就能可变引用(reference):

fn main() {
    let mut s = String::from("hello");

    change(&mut s);
}

fn change(some_string: &mut String) {
    some_string.push_str(", world");
}

首先,我们更改s为mut。&mut s然后我们在调用函数的地方创建一个可变引用change,并更新函数签名以接受一个可变引用some_string: &mut String。这清楚地表明该change函数将改变它借用的值。

可变引用有一个很大的限制:一次只能有一个对特定数据的可变引用。尝试创建两个可变引用的代码s将失败:

    let mut s = String::from("hello");

    let r1 = &mut s;
    let r2 = &mut s;

    println!("{}, {}", r1, r2);
上面的代码是错误的

如果使用2个变量来访问可变引用,需要加一个{}来做作用域隔离。

let mut s = String::from("hello");

    {
        let r1 = &mut s;
    } // r1 goes out of scope here, so we can make a new reference with no problems.

    let r2 = &mut s;
这个代码是允许的。

可变引用和 不可变引用 是不能同时存在的

    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    let r3 = &mut s; // BIG PROBLEM

    println!("{}, {}, and {}", r1, r2, r3);
但是可以在引用r1,r2之后在用r3。

下面的代码是可以的。

    let mut s = String::from("hello");

    let r1 = &s; // no problem
    let r2 = &s; // no problem
    println!("{} and {}", r1, r2);
    // variables r1 and r2 will not be used after this point
   这之后r1,r2不再使用了
    let r3 = &mut s; // no problem
    println!("{}", r3);

悬空引用

fn main() {
    let reference_to_nothing = dangle();
}

fn dangle() -> &String {
    let s = String::from("hello");

    &s
}

s的作用域在dangle函数范围内,当dangle结束了,s会被释放。 这时候引用会被出错。

只能把s返回,延续s的所有权

fn no_dangle() -> String {
    let s = String::from("hello");

    s
}