rust 语法和语义 10 引用和借用
引用和借用 references and borrowing
所有权概念将依照官方介绍,分为3个部分说明:
- 所有权 ownership
- 引用和借用 references and borrowing
- 生命周期 lifetimes
概述
操作格式 | 声明 | example |
---|---|---|
&T | 引用(对象不可变) | &Vec |
&mut T | 引用(对象 可变) | &mut Vec |
* | 访问 可变对象的引用 | {let y = &mut x; *y += 1;} |
- & 似乎类似 c 中的取地址操作,获得一个指针
- * 似乎类似 c 中的取地址内容的操作,获得指针所存地址里的内容
<注意!> 借用规则
和 引用生命周期
。
引用 reference
&T // 引用(不可变) // e.g. &Vec<i32>
- 引用是
借用
了所有权,而不是拥有
所有权。 - 一个借用变量的绑定,在它离开作用域时并不释放原始资源。
- 引用是
不可变的 immutable
,
可变引用:
&mutT // 引用( 可变) // e.g. &mut Vec<i32>
借用规则
- 任何
borrowing
必须比拥有者
更小的作用域
。 - 同一个 resource 的 borrowing,即
同一个作用域
下:
- 只有
N
个 不可变的引用 &T 或者 - 只有
1
个 可变的引用 &mut T
- 只有
当 2 个或更多个指针同时访问同一内存位置,当它们中至少有 1 个在写(那1个
可变的引用 &mut T
),同时操作在并不是同步的时候存在一个“数据竞争”。
所以解释了为什么下面的代码会出错:
fn main() {
let mut x = 5;
let y = &mut x; // a mutable borrowing start here
*y += 1;
println!("{}", x); // a immutable borrowing try immut borrow
} // a mutable borrowing end here
可变借用 可以在创建一个 不可变引用 之前离开作用域:
fn main() {
let mut x = 5;
{
let y = &mut x; // a mutable borrowing start here
*y += 1;
} // a mutable borrowing end here
println!("{}", x); // a immutable borrowing
}
引用生命周期
引用必须与它引用的值存活得一样长。不然会如 C 一样引起 内存泄漏。
豆知识
- 释放正在使用的指针,内存损坏
- 未释放不使用的指针,内存泄漏