Q5: 一個函數的觀點
A5: Rust中的每個函數都是自治的,在每一個函數體中,相當於重新開辟了一個新的領域。
將參數傳遞給函數參數,與let聲明一個綁定是一樣的規則。
1 ``` 2 // 所有權語義 3 fn modify(mut v: Vec<u32>) -> Vec<u32> { 4 v.push(42); 5 v 6 } 7 let v = vec![1,2 ,3]; 8 let v = modify(v); // 這里參數傳遞到modify執行的綁操作是, let mut v = v;是以所有權的方式轉移的 9 println!("{:?}", v); // 1, 2, 3, 42 10 11 // 同上面進行對比 12 let v = vec![1, 2, 3]; 13 let mut v = v; // 這里可以看出很多的問題了吧,使用到了變量遮蔽,將變量重新綁定的位可變的變量,這里是符合所有權的,因為還是只有一個值指向管理的內存,原來的v的所有權給了新的v,只不過這里的兩個v是相同的名字而已。 14 v.push(42); 15 println!("{:?}", v); 16 17 18 // 借用 19 pub fn modify_ref_mut(v: &mut [u32]) { 20 v.reverse(); 21 } 22 let mut v = vec![1,2,3]; 23 modify(&mut v); // 這里參數傳遞到modify執行的綁定是,let v = &mut v; 是以可變引用的方式借用的 24 println!("{:?}", v); // 3, 2, 1 25 26 // 同上面對比 27 let mut v = vec![1, 2, 3]; 28 let v = &mut v; // 聲明了一個可變借用 29 v.reverse(); // 對可變借用進行操作 30 println!("{:?}", v); 31 32 // 可變借用和不可變借用同時存在 33 // Case 1 ok 34 let mut v = vec![1, 2, 3]; 35 36 let v1 = &mut v; // 可變借用 37 v1.reverse(); 38 println!("{:?}", v1); // 不可變借用 39 40 // 此時的 v 已經被v1改變了 41 42 let v2 = &v; // 不可變借用, 此時v2做出了一個不可變綁定 43 println!("{:?}", v2); // 不可變借用, 從上一句到這一句之間不會不發生v的任何變化ok 44 45 // Case 2 ok 46 let mut v = vec![1, 2, 3]; 47 48 let v2 = &v; // 不可變借用 49 println!("{:?}", v2); // 不可變借用, 從上一句到這一句之間不會發生v的任何變化ok 50 51 // v1 可變借用了v 52 53 let v1 = &mut v; // 可變借用 54 v1.reverse(); 55 println!("{:?}", v1);// 不可變借用 56 57 // Case 3 error 58 let mut v = vec![1, 2, 3]; 59 60 let v2 = &v; // 不可變借用 61 62 63 // v1 可變借用了v 64 let v1 = &mut v; // 可變借用 65 v1.reverse(); 66 println!("{:?}", v1); 67 println!("{:?}", v2); // 不可變借用, 這里的v2和上面聲明的v2之間指向的v發生了變化, 68 及時沒有任何的變化,在let v2 = &v; 和println!("{:?}", v2);有任何的可變借用都不可以。所以發生了借用規則的沖突問題。
1 error[E0502]: cannot borrow `v` as mutable because it is also borrowed as immutable 2 --> src/lib.rs:75:14 3 | 4 73 | let v2 = &v; 5 | -- immutable borrow occurs here 6 74 | 7 75 | let v1 = &mut v; 8 | ^^^^^^ mutable borrow occurs here 9 ... 10 78 | println!("{:?}", v2); 11 | -- immutable borrow later used here
從這個例子可以看到的是, modify中參數的是被mut修飾是一個可變的,而傳入的v是沒有被mut
修飾的,這里參數傳遞進來進行了一次綁定操作,let mut v = v;
在函數modify的內部v與函數外部的v沒有任何的關系,v被轉移到了modify的內部。從這里可以
看出每一個函數是一個自治的。
