Rust的所有权与可变性

Rust的所有权与可变性,第1张

Rust的所有权与可变性 Rust与其他语言的比较

文章目录
  • 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 = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10].to_vec();,我们需要分别获取它们累加、累乘的结果。为了不丢失所有权,直接使用nums变量进行迭代获取结果显然是可行的,但并不优雅。我们可以分别实现累加、累成的函数进行 *** 作。

这样的函数签名大概是这样的形式fn sum(arr: Vec)->i32、fn mult(arr: Vec)->i32。

但这会引发一个问题:间接转移test3代码段即存在这样的问题。当_v变量作为实参传入change函数时,_v的所有权就已经被转移到了change函数的形参v中,这意味着change一旦执行,_v则已丧失所有权,不可访问。

而这样的情况函数签名若是以fn sum(arr: Vec)、fn mult(arr: Vec)的形式,那么意味着我们至多只能执行其中的一个sum或是mult,因为nums的所有权会在执行他们的其中一个时就已经转移丢失了。

所以为了保持其原有的所有权,我们需要有一种借用它的方式,这样的方式就是引用。针对累加、累乘,我们就可以写出这样的代码。

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 vector array = 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
}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5520799.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-13
下一篇 2022-12-13

发表评论

登录后才能评论

评论列表(0条)

保存