Rust函数参数传递的一个观点
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的内部。从这里可以
看出每一个函数是一个自治的。