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的内部。从这里可以

看出每一个函数是一个自治的。