Borrowing 继续讲讲另一个重要的概念:借用(borrowing), 什么是借用? 我们先来看前一文章(\[[易学易懂系列|rustlang语言|零基础|快速入门|(3)\]](https://www.cnblogs.com/gyc567/p/11910013.html))的代码 : ~~~ let a = [1, 2, 3]; ​ let b = a; ​ println!("{:?} {:?}", a, b); *// [1, 2, 3] [1, 2, 3]* ​ let a = vec![1, 2, 3]; ​ let b = a; ​ println!("{:?} {:?}", a, b); *// Error; use of moved value: `a`* ~~~ 我们从上篇文章知道,第二段代码会报错,那怎么才能不报错呢? 我们改成以下代码: ~~~ let a = vec![1, 2, 3]; ​ let b = **&**a;//这里加了一个符号:**&**,表示借用 ​ println!("{:?} {:?}", a, b); *// correct* ~~~ 现在可以顺利通过傲娇的编程器女王的检查了!这就是“借用”的功效! 这里就出来一个rust语言的概念,叫借用(borrowing)。 来看下定义: 英语:[Borrow (verb)](https://github.com/nikomatsakis/rust-tutorials-keynote/blob/master/Ownership%20and%20Borrowing.pdf)To receive something with the promise of returning it. 翻译成中文:出来混,借了东西,迟早要还的! 那借用又分两类型: 1.共享借用(**Shared Borrowing**`(&T)`) 数据可以借用给一个或多个用户(或线程),但只准一个用户修改。 2.可变借用(**Mutable Borrowing**`(&mut T)`) 数据可以借用给一个用户,并只准这个用户修改,同时不准其他用户访问。 借用规则如下 : 1.数据同一时间,只能是其中一种借用,要么是共享借用(**Shared Borrowing**`(&T)`),要么是可变借用(**Mutable Borrowing**`(&mut T)`)。 2.借用概念适用于复制类型(Copy type )和移动类型(**Move type**)。 请看如下代码: ~~~ fn main() {  let mut a = vec![1, 2, 3];  let b = &mut a;  // &mut borrow of `a` starts here                   // ⁝  // some code     // ⁝  // some code     // ⁝ }                  // &mut borrow of `a` ends here ​ ​ fn main() {  let mut a = vec![1, 2, 3];  let b = &mut a;  // &mut borrow of `a` starts here  // some code ​  println!("{:?}", a); // trying to access `a` as a shared borrow, so giving an error }                  // &mut borrow of `a` ends here ​ ​ fn main() {  let mut a = vec![1, 2, 3]; {    let b = &mut a;  // &mut borrow of `a` starts here    // any other code }                  // &mut borrow of `a` ends here ​  println!("{:?}", a); // allow borrowing `a` as a shared borrow } ~~~ 从上面代码,我们可以看出,借用,也是有“生命周期”的。 像这段代码 : ~~~ fn main() {      let mut a = vec![1, 2, 3];    let b = &mut a; // &mut borrow of `a` starts here // some code ​    println!("{:?}", a); // trying to access `a` as a shared borrow, so giving                         //an error } // &mut borrow of `a` ends here ~~~ 为什么会报错?因为当最后一行代码: ~~~ println!("{:?}", a); ~~~ 要访问a时,a对数据的所有权,已经借用给b了。a已经没有数据所有权。所以报错。 那要怎么办? 加上大括号“{}”。 如下 : ~~~ let mut a = vec![1, 2, 3]; {    let b = &mut a;  // &mut borrow of `a` starts here    // any other code }                  // &mut borrow of `a` ends here ​  println!("{:?}", a); // allow borrowing `a` as a shared borrow ~~~ 加上{}后,把借用,限定在大括号内,大括号结束后,b会把**所有权还给**a。 这时,a对数据有了所有权,就可以访问数据了! 那共享借用和可变借用有什么区别呢,请看代码如下 : 共享借用: ~~~ fn main() {    let a = [1, 2, 3];    let b = &a;    println!("{:?} {}", a, b[0]); // [1, 2, 3] 1 } ​ ​ fn main() {    let a = vec![1, 2, 3];    let b = get_first_element(&a); ​    println!("{:?} {}", a, b); // [1, 2, 3] 1 } ​ fn get_first_element(a: &Vec<i32>) -> i32 {    a[0] } ~~~ 第一段代码: ~~~ fn main() {    let a = [1, 2, 3];    let b = &a;    println!("{:?} {}", a, b[0]); // [1, 2, 3] 1 } ~~~ 这里a借用给了b,为什么a还可以访问呢?因为a的类型是数组,是基本类型。这是复制类型,共享借用,只借用复制数据。所以,原来a还是拥有对原始数据的所有权。 第二段代码: ~~~ fn main() {    let a = vec![1, 2, 3];    let b = get_first_element(&a); ​    println!("{:?} {}", a, b); // [1, 2, 3] 1 } ​ fn get_first_element(a: &Vec<i32>) -> i32 {    a[0] } ~~~ 这里定义一个函数,get\_first\_element,返回值为数组中的第一个值。b从函数中得到值1。没有什么问题。 现在我们修改一下函数get\_first\_element的代码,如下 : ~~~ fn get_first_element(a: &Vec<i32>) -> i32 { ​ a[0]=9; ​ a[0] ​ } ~~~ 这时,傲娇的编译器女王,又扔出一个错误给你: ~~~ fn get_first_element(a: &Vec<i32>) -> i32 {   | --------- help: consider changing this to be a mutable reference: `&mut std::vec::Vec`   | a[0]=9; |     ^ `a` is a `&` reference, so the data it refers to cannot be borrowed as mutable ~~~ 这些错误信息很清楚地告诉你: 你现在是共享借用,共享借用只能共享数据,不能修改!(这里的真实含义是:**共享借用了数据,没有所有权,如果没有所有权,就没有修改权,只有拥有所有权,才有修改权!**) 那要修改怎么办?用可变借用啊! 把代码修改为如下就可以了: ~~~ fn main() {   let mut a = vec![1, 2, 3]; let b = get_first_element(&mut a);//从函数get_first_element返回后,把数据所有权还给a ​ ​ println!("{:?} {}", a, b); // [9, 2, 3] 9 ​ ​ } ​ fn get_first_element(g: &mut Vec<i32>) -> i32 { //开始借用 a的数据  g[0]=9;  g[0] ​ }//结束借用 a的数据,返回到main函数后,把数据所有权还给a ~~~ 以上代码,已经把**不可变**变量a改为**可变**变量,**共享变量**&a改为**可变共享**&mut a。 在上面的代码中,a所绑定的数据的**所有权(ownership)**已经**移动**(**move**),也就是说数据**所有权(ownership)**已经从a转交到函数get\_first\_element的参数变量g,在函数get\_first\_element内,修改了数据的内容,然后返回main函数,并把数据所有权**还给**绑定变量a,这时数据内容已经更新。 所以打印结果为: ~~~ [9, 2, 3] 9 ~~~ 再看看可变借用完整例子: ~~~ fn main() {    let mut a = [1, 2, 3];    let b = &mut a;    b[0] = 4;    println!("{:?}", b); // [4, 2, 3] } ​ ​ fn main() {    let mut a = [1, 2, 3];   {        let b = &mut a;        b[0] = 4;   } ​    println!("{:?}", a); // [4, 2, 3] } ​ ​ fn main() {    let mut a = vec![1, 2, 3];    let b = change_and_get_first_element(&mut a); ​    println!("{:?} {}", a, b); // [4, 2, 3] 4 } ​ fn change_and_get_first_element(a: &mut Vec<i32>) -> i32 {    a[0] = 4;    a[0] } ~~~ 所以,我们结合**所有权(Ownership)**和**借用(Borrowing)**两个概念来理解。 得出来一个重要结论: 1.**没有所有权,就没有修改权,只有拥有所有权,才有修改权**。 2.**共享借用,不会转交数据所有权,所以借用者,没有修改权,借用者归还数据所有权后,数据内容不变。** 3.**可变借用,会转交数据所有权,所以借用者,拥有修改权,借用者归还数据所有权后,数据内容可能已经改变**。 **4.这里的“借用”,其实可以跟“引用”划上等号,共享借用,也就是共享引用(或不可变引用),可变借用,也就是可变引用,但它们都是跟数据所有权结合一起的。** 以上,希望对你有用。