Skip to content

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;
    }
}

借用指针在编译后,实际上就是一个普通的指针,它的意义只能在编译阶段的静态检查中体现。

Released under the MIT License