Rust-引用和借用

430 阅读3分钟

这是我参与11月更文挑战的第25天,活动详情查看:2021最后一次更文挑战

引用与接用

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

    let (s2, len) = calculate_length(s1);  // s1被移动到函数内,如果想要在该作用域中继续使用该变量的值,函数就必须返回这个值。

    println!("The length of '{}' is {}.", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {  // s进入作用域
    let length = s.len(); // len() 返回字符串的长度

    (s, length)
}  // s移出作用域,Rust执行drop方法

在上述代码中,有一个这样的问题,就是必须将String返回给调用函数,以便在调用calculate_length之后仍然能够使用String,因为String被移动到了 calculate_length中。

下面就是如何定义并使用一个(新的)calculate_length 函数,它以一个对象的引用作为参数而不是获取值的所有权

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 是对 String 的引用
    s.len()
} // 这里,s 离开了作用域。但因为它并不拥有引用值的所有权,
  // 所以什么也不会发生

首先,注意变量声明和函数返回值中的所有元组代码都消失了。其次,注意我们传递 &s1calculate_length,同时在函数定义中,我们获取 &String 而不是 String

这个&符号就是引用,该符号允许你使用值但不获取其所有权,原理如下图所示:

image-20211122164541999

&s1 语法让我们创建一个 指向s1 的引用,但是并不拥有它。因为并不拥有这个值,当引用离开作用域时其指向的值也不会被丢弃。同理,函数签名使用 & 来表明参数 s 的类型是一个引用。

变量 s 有效的作用域与函数参数的作用域一样,不过当引用离开作用域后并不丢弃它指向的数据,因为我们没有所有权。当函数使用引用而不是实际值作为参数,无需返回值来交还所有权,因为就不曾拥有所有权。

我们将获取引用作为函数参数称为 借用borrowing)。正如现实生活中,如果一个人拥有某样东西,你可以从他那里借来。当你使用完毕,必须还回去。

如果我们尝试修改借用的变量呢?这肯定是行不通的,如下述代码:

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

    change(&s);
}

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

如果运行上述代码则会出现下述错误,正如变量默认是不可变的,引用也一样。(默认)不允许修改引用的值。:

error[E0596]: cannot borrow immutable borrowed content `*some_string` as mutable
 --> error.rs:8:5
  |
7 | fn change(some_string: &String) {
  |                        ------- use `&mut String` here to make mutable
8 |     some_string.push_str(", world");
  |     ^^^^^^^^^^^ cannot borrow as mutable

如果就是想要修改借来的变量怎么办呢?也并非不可能,作者留一个小悬念哦,我们在下一篇文章中提供如何修改借来的变量,期待一下哦~

结语

文章首发于微信公众号程序媛小庄,同步于掘金

码字不易,转载请说明出处,走过路过的小伙伴们伸出可爱的小指头点个赞再走吧(╹▽╹)