Appearance
12.2 借用
变量对其管理的内存拥有所有权。借用就是一个值的所有权在不发生转移的情况下,借给其他变量使用。
要使用借用,需要先使用引用语法(&
或&mut
)创建一个引用,前者表示只读借用,后者表示可读写借用。 创建的引用只是拥有临时的使用权,而没有所有权。
在 Rust 中引用和借用说的是一回事,Rust 中将创建一个引用的行为称为借用(borrowing)。
借用指针与普通指针的内部数据是一模一样的,唯一的区别是语义层面上的。它的作用是告诉编译器,它对指向的这块内存区域没有所有权。
示例如下:
rust
fn foo(v: &Vec<i32>) {
v.push(5);
}
fn main() {
let v = vec![];
foo(&v);
}
这里会出现编译错误,信息为“v
is a &
reference, so the data it refers to cannot be borrowed as mutable”。
原因在于Vec::push
函数。它的作用是对动态数组添加元素,它的签名是:
rust
pub fn push(&mut self, value: T)
它要求 self 参数是一个&mut Self
类型。而我们给 foo 传递的参数是&Vec
类型,因此会报错。修复方式如下:
rust
// 我们需要“可变的”借用指针,因此函数签名需要改变
fn foo(v: &mut Vec<i32>) {
v.push(5);
}
fn main() {
// 我们需要这个动态数组本身是“可变的”,才能获得它的“可变借用指针”
let mut v = vec![];
// 在函数调用的时候,同时也要显示获取它的“可变借用指针”
foo(&mut v);
// 打印结果,可以看到 v 已经被改变
println!("{:?}", v);
}
对于&mut
型指针,请大家注意不要混淆它与变量绑定之间的语法。 如果mut
修饰的是变量名,那么它代表这个变量可以被重新绑定;如果 mut 修饰的是“借用指针&
”,那么它代表的是被指向的对象可以被修改。
示例如下:
rust
fn main() {
let mut var = 0_i32;
{
let p1 = &mut var; // p1 指针本身不能被重新绑定,我们可以通过 p1 改变变量 var 的值
*p1 = 1;
}
{
let temp = 2_i32;
let mut p2 = &var; // 我们不能通过 p2 改变变量 var 的值,但 p2 指针本身指向的位置可以被改变
p2 = &temp;
}
{
let mut temp = 3_i32;
let mut p3 = &mut var; // 我们既可以通过 p3 改变变量 var 的值,而且 p3 指针本身指向的位置也可以改变
*p3 = 3;
p3 = &mut temp;
}
}
借用指针在编译后,实际上就是一个普通的指针,它的意义只能在编译阶段的静态检查中体现。