- Rust与其他语言的比较
- 特性
- 所有权
- 直接转移
- 间接转移
- 引用、借用
- 可变性与不可变性
在Rust中,若声明有类似于Java或C++中的引用传递类型概念的变量,存在相同作用域下将地址赋值给另一个变量,则该变量的所有权将发生转移,原先的变量将不可访问。
直接转移fn test2() { let a:Vec间接转移= Vec::new(); a.push(1); let b = a; //将a的所有权转移给b println!("{}", a[0]); // 试图访问已丧失所有权的变量a }
fn test3() { let _v:Vec= Vec::new(); _v.push(1); let change = |v:Vec | -> () { return; }; change(_v); println!("{}", _v[0]); // 试图访问已丧失所有权的变量_v }
引用、借用
在Rust中,由于有所有权的特性,若想用另一个变量去读取其值进行一些 *** 作,而又不会丢失其所有权,可以使用引用特性,使用方式是将&加在变量名前。
事实上这样的场景十分常见。
如,现在有一个let nums:Vec
这样的函数签名大概是这样的形式fn sum(arr: Vec
但这会引发一个问题:间接转移test3代码段即存在这样的问题。当_v变量作为实参传入change函数时,_v的所有权就已经被转移到了change函数的形参v中,这意味着change一旦执行,_v则已丧失所有权,不可访问。
而这样的情况函数签名若是以fn sum(arr: Vec
所以为了保持其原有的所有权,我们需要有一种借用它的方式,这样的方式就是引用。针对累加、累乘,我们就可以写出这样的代码。
fn sum(arr: &Vec可变性与不可变性) ->i32 { let mut ans = 0; for n in arr.iter() { ans += n; } ans } fn mult(arr: &Vec ) ->i32 { let mut ans = 1; for n in arr.iter() { ans *= n; } ans } let nums:Vec = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].to_vec(); let ans1 = sum(&nums); // 通过引用传递nums,保证nums不会丢失所有权,下同 let ans2 = mult(&nums); println!("sum:{} mult:{}", ans1, ans2); }
Rust的let关键字自带const(不可变)性质,但与Javascript、C++的const关键字带来的效果略有差异。在Javascript、C++以修饰的const的变量,只为了确保其变量所指向堆区的地址是否发生变化,而不关心其地址指向堆中的内存区域的数据是否有所改变。
在Typescript中,以下代码段是合法的。
const array: Array= []; // 声明一个名为array,int类型的数组 array.push(1); // 为array添加一个元素1
在C++中,以下代码段是合法的。
const vectorarray = vector (); // 声明一个名为array,int类型的数组 array.push_back(1); // 为array添加一个元素1
而Rust不是这样的,任何变量,没有经过mut关键字的修饰,无论是栈中的内存数据还是堆区的内存数据,都是不可改变的。
let array:Vec= Vec::new(); // 声明一个名为 array.push(1); // 尝试为array添加一个元素1,不可行
而如果想要为其添加元素,则必须使用mut关键字修饰。
fn test5() { let mut _v:Vec= Vec::new(); _v.push(1); // 直接添加 let change = |v:& mut Vec | -> () { v.push(3); return; }; change(&mut _v); println!("{}", _v[1]); // 可以成功获取change函数添加的元素3 }
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)