《Rust编程入门》6.2 借用与引用规则
6.2 借用与引用规则
借用是 Rust 的另一个核心特性,它允许多个部分共享数据,而无需将数据的所有权转移。借用通过引用(references)来实现,可以分为不可变借用和可变借用两种形式。在 Rust 中,借用是为了在保证内存安全的同时,避免不必要的数据复制,并提高程序的性能。
6.2.1 引用的基本概念
在 Rust 中,引用是通过符号 &
来创建的。引用指向某个值,但不拥有它,因此它不会影响所有权的转移。
不可变引用
不可变引用允许你查看数据,但不允许修改它。多个不可变引用可以同时存在,因为它们不会改变数据。
|
|
在这个例子中,r1
和 r2
是对 s
的不可变引用,它们允许读取 s
的数据,但不能修改它。
可变引用
可变引用允许修改所引用的数据。然而,Rust 的规则是:在某一时刻,某个数据只能有一个可变引用,不能同时存在多个可变引用或同时存在不可变引用和可变引用。这样做是为了防止数据竞争和并发访问时发生的不确定行为。
|
|
在上面的例子中,r1
是一个可变引用,它允许修改 s
的值。如果你尝试在同时拥有可变引用的情况下再创建不可变引用,Rust 编译器会报错。
不可变引用和可变引用的混用
Rust 的规则禁止在同一作用域中同时拥有不可变引用和可变引用。这是为了防止发生“数据竞争”(data race)。
|
|
6.2.2 借用的生命周期
借用的生命周期受制于 Rust 的生命周期规则。借用的生命周期必须在数据的有效范围内,并且不能比数据本身的生命周期长。换句话说,引用不能比它所引用的数据活得更久。
函数中的引用
当函数接受引用作为参数时,Rust 会通过生命周期标注来确保引用的有效性,防止悬空引用(dangling reference)和内存泄漏。
|
|
- 在这个例子中,
print_string
函数接受一个对String
类型数据的不可变引用,它不会获得所有权,只会读取数据。
可变引用的生命周期
对于可变引用,它的生命周期要小于或等于数据的生命周期,因为在数据修改过程中,其他部分不能使用数据。
|
|
在这个例子中,modify_string
函数接受一个可变引用并修改它。在调用期间,s
只能通过可变引用 s
来访问,而其他地方不能使用 s
。
6.2.3 借用的规则
-
可变借用与不可变借用不能同时存在。
- 在同一作用域内,如果存在对某数据的可变引用,那么就不能同时存在不可变引用,反之亦然。
-
引用的生命周期不能超过数据的生命周期。
- 引用数据的生命周期不能超过原数据的生命周期,以确保引用始终有效。
-
多次不可变借用是允许的。
- 如果所有的引用都是不可变引用,那么可以有多个引用同时存在。因为不可变引用不会改变数据,它们是安全的。
-
一个数据只能有一个可变引用。
- 为了避免并发访问带来的数据竞争,每个数据在同一作用域内最多只能有一个可变引用。
6.2.4 通过函数返回引用
Rust 允许函数返回对数据的引用,但它会受到生命周期的限制。返回的引用必须确保它指向的数据在调用者中仍然有效。
返回引用的生命周期
|
|
在这个例子中,函数 longest
接受两个字符串的引用,并返回其中较长的那个字符串的引用。'a
是生命周期参数,表示返回的引用的生命周期与输入参数的生命周期相同。
6.2.5 小结
- 借用 是 Rust 内存管理的一部分,它允许在不转移所有权的情况下共享数据。借用分为不可变借用和可变借用两种形式。
- Rust 强制要求在同一作用域内不可同时拥有可变借用和不可变借用,以避免数据竞争。
- 引用的生命周期与原数据的生命周期密切相关,Rust 使用生命周期标注来确保引用的安全性。
- 引用 使得我们能够高效地传递数据,而不需要复制数据,这对于性能和内存管理至关重要。
下一节将深入探讨 Rust 中 生命周期的定义与用法,了解 Rust 如何通过生命周期来保证数据的安全性。