Skip to content
Word Count: 795 | Expected Read Time: 2 min

下雨天生生锈 - 02

前言

和很久没见的初中同学一起吃了午饭,虽然已经毕业3年,看上去已然成熟一些的他依然有着不变的热爱与梦想,有梦想的人一定会活得很快乐。等我拿到第一笔实习工资的时候,兴许也能回来请他吃一顿😄

虽然不早了,还是挤出点时间给今天的Rust笔记吧,学习这种事情切不可三分钟热度。

接上昨天的所有权,今天接着看引用与借用

(这中文的Rust圣经比英文的C教材看的舒适多了)

Chapter 3 所有权和借用

3.2 引用与借用

在Rust中,也可以使用像C语言一般的引用与解引用。例如:

1
2
3
4
5
6
7
fn main() {
let x = 5;
let y = &x;

assert_eq!(5, x);
assert_eq!(5, *y);
}

不可变引用

举一个生动的例子,我想要创建一个计算字符串长度的函数:

1
2
3
4
5
6
7
8
9
10
11
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()
}

使用C语言中指针的概念去理解,这段代码的含义非常易懂。传入s1的引用,计算其引用的长度,然后返回长度。

用Rust的概念去说,在这段代码中,我们只传递了s1的引用,并没有把其所有权转移给该函数

&符号,只允许使用值,但是不获取所有权

顺着这个逻辑,函数中的s不拥有字符串的所有权,所以在s离开其作用域时,不会有任何事情发生,其指向的值也不会被丢弃。

得寸进尺的人类

那如果,我就想……动一下…………就稍微动一下人家的值呢🤓

嘿嘿,想多了。不可变引用类型时不能修改值滴。

可是如果非要猥琐一下的话,也不是没办法

可变引用

1
2
3
4
5
6
7
8
9
fn main() {
let mut s = String::from("hello");

change(&mut s);
}

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

只需要声明参数类型为&mut String,我们就可以随意更改引用量啦。

用朴素方式看:

  • 借用不可变引用的用户,肯定不希望他借用的东西,被另外一个人莫名其妙改变了。

  • 多个不可变引用,不会导致被借走的东西被不可控的篡改

  • 多个可变引用,无法控制被借走的数据的一致性

所以:

  • Rust规定在同一个作用域,一个数据只能有一个可变引用
  • 可变引用和不可变引用不能同时存在

如下代码是一个典型的错误用例:

1
2
3
4
5
6
let mut s = String::from("hello");

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

println!("{}, {}", r1, r2);

同时为了优化Rust的使用体验,新版本的Rust规定:引用作用域的结束位置是最后一次使用的位置

总的来说,借用规则如下:

  • 同一时刻,你只能拥有要么一个可变引用,要么任意多个不可变引用
  • 引用必须总是有效的

后记

十一点半,终于是写完了,洗澡!睡觉!!

About this Post

This post is written by Jinyuan Zhou, licensed under CC BY-NC 4.0.

#Rust,学习笔记