大家好,我是梦兽编程。欢迎回来与梦兽编程一起刷Rust的系列。
这是由 Google 的 Android 团队开发的免费 Rust 课程。本课程涵盖了 Rust 的方方面面,从基本语法到泛型和错误处理等高级主题。
该课程的最新版本可以在 google.github.io/comprehensi…
如果你喜欢看梦兽编程的版本可以定义跟着谷歌安卓团队学Rust定于最新内容,梦兽编程也期待大家关注我的个人网站。
引用
与C++一样,Rust一样提供了引用的概念在Rust中。
引用是一种指向另一个值的变量。引用可以是可变的(mutable)或不可变的(immutable)。
Rust的引用非常简单
引用的语法很简单,就是在变量名之前加上一个&符号。例如,以下代码定义了一个可变引用:
fn main() {
let mut x: i32 = 10;
let ref_x: &mut i32 = &mut x;
*ref_x = 20;
println!("x: {x}");
}
以上代码,如果我们修改了ref_x的值,我们x值也会同时被改变,这就是引用的作用。
在内存中其实是指向了同一块内存地址。我们可以使用type_of方法进行对比,可以发现基础类型的地址是指向同一块。
assert_eq!(type_of!(ref_x), type_of!(x));
// output
// ture
注意悬垂引用
Rust 其实是一个半自动的内存机制,也就是在代码块执行后Rust会尝试给我们释放资源比如以下代码:
fn main() {
let ref_x: &i32;
{
let x: i32 = 10;
ref_x = &x;
}
println!("ref_x: {ref_x}");
}
在这种请求下,在别的生命周期中进行了一次引用我们又把这种引用叫做借用。在这种情况下我们需要保证我们的我们引用的变量活的比较久。
这是因为 ref_x 在 { } 块内被初始化为 &x,但 x 在 { } 块结束时被销毁。因此,ref_x 在 { } 块结束时仍然引用一个已经被销毁的值,这会导致悬垂引用。
什么是借用?
Rust 的借用机制是 Rust 语言中的一个重要概念。借用机制可以帮助 Rust 编译器确保引用的安全性,避免悬垂引用。
在 Rust 中,借用是指引用一个值的权利。引用可以是不可变的(immutable)或可变的(mutable)。 不可变引用只能读取引用的值,不能修改引用的值。可变引用可以读取和修改引用的值。
“
借用没有和网上过多的复杂概念,它只不过是你对引用值的使用权限是否有写的操作。
借用的规则
在 Rust 中,借用遵循以下规则:
- 同一个作用域内,引用必须是有效的。最经典的反面例子就是返回局部变量的引用:
fn dangle() -> &String {
let s = String::from("hello");
&s
}
- 同一个作用域内,只允许有一个可变引用或者多个只读引用。
// 这种情况就是你已经被可变应用借用了,在定义只读引用,那就存在问题。
fn main() {
let mut str1 = String::from("adasdsa");
let str2 = &mut str1;
let str3 = &str1;
str1 += "adad";
println!("{}", str1);
}
生命周期的概念在后面会讲到,我们先有个概念知道引用的生命周期可以用于实现各种功能,例如:
- 避免悬垂引用
- 实现智能指针
- 实现并发编程
悬垂引用
悬垂引用是指引用指向的值已经被销毁了。悬垂引用会导致程序崩溃。
Rust 的引用机制可以帮助避免悬垂引用。引用的生命周期必须与它引用的值的生命周期相同。因此,如果引用引用的值被销毁了,则引用的生命周期也会结束。
智能指针
智能指针是一种自动管理内存的类型。Rust 提供了一些内置的智能指针,例如 Box、Rc 和 RefCell。 智能指针可以帮助避免悬垂引用。智能指针会在值被销毁时自动释放引用。
并发编程
在并发编程中,多个线程可能同时访问同一个值。如果这些线程都使用引用来访问这个值,则必须确保这些引用的生命周期是安全的。
Rust 的引用机制可以帮助确保引用的生命周期安全。引用的生命周期必须与它引用的值的生命周期相同。因此,如果一个线程正在修改一个值,则其他线程不能使用引用来访问这个值。
参考资料
[1]
google.github.io/comprehensi…: google.github.io/comprehensi…
[2]
跟着谷歌团队学Rust: rexweb.link/category/te…
[3]
梦兽编程: rexweb.link