Rust - 所有权和函数

本文探讨了Rust编程语言中所有权规则如何影响函数参数和返回值。通过示例代码,说明了值在传递给函数时可能会移动或复制,以及如何通过函数返回值转移所有权。文章还提到了引用的概念,作为在不转移所有权的情况下使用值的一种方式。
摘要由CSDN通过智能技术生成

本文主要介绍一下Rust的所有权与函数之间的关系,我们知道将值传递给函数在语义上和给变量赋值时相似的,像函数传递值也可能会移动或者复制,就像变量与数据的两种交互方式一样,下面通过代码示例对Rust所有权和函数之间的关系进行解释说明。

所有权与函数

以下述代码示例对变量何时进入和离开作用域进行说明:

fn main() {
    let s = String::from("hello");  //  变量s进入作用域
    
    move_variable(s);  // s 的值被移动到move_variable函数中
    					// 因此在这里s已经不再有效
    
    let x = 1;  // 变量x进入作用域
    
    makes_copy(x);  // x应该移动到函数中,但是i32类型时copy的,因此x变量的作用域中还可以继续使用x变量
    
} // 这里 x 先移出了作用域,然后是s,但是因为s的值已经被移走,所以对s没有任何操作

fn move_variable(string_str: String) {  // string_str进入作用域
    println!("str is {}", string_str);
}  // string_str移出作用域 Rust调用drop方法回收被string_str占用的内存

fn makes_copy(some_integer: i32) { // some_integer 进入作用域
    println!("{}", some_integer);
} // 这里,some_integer 移出作用域。不会有特殊操作

当尝试在调用 move_variable后使用 s时,Rust 会抛出一个编译时错误。这些静态检查使我们免于犯错。小伙伴们可以试试在 main函数中添加使用 s和 x的代码来看看哪里能使用他们,以及所有权规则会在哪里阻止我们这么做。

函数返回值和作用域

函数的返回值也可以转移其所有权,以下述代码为例进行说明:

fn main() {
    let s1 = gives_ownership();         // gives_ownership 将返回值
                                        // 移给 s1

    let s2 = String::from("hello");     // s2 进入作用域

    let s3 = takes_and_gives_back(s2);  // s2 被移动到
                                        // takes_and_gives_back 中,
                                        // 它也将返回值移给 s3
} // 这里, s3 移出作用域并被丢弃。s2 也移出作用域,但已被移走,
  // 所以什么也不会发生。s1 移出作用域并被丢弃

fn gives_ownership() -> String {             // gives_ownership 将返回值移动给
                                             // 调用它的函数

    let some_string = String::from("hello"); // some_string 进入作用域.

    some_string                              // 返回 some_string 并移出给调用的函数
}

// takes_and_gives_back 将传入字符串并返回该值
fn takes_and_gives_back(a_string: String) -> String { // a_string 进入作用域

    a_string  // 返回 a_string 并移出给调用的函数
}

变量的所有权总是遵循相同的模式:将值赋给另一个变量时移动它。当持有堆中数据值的变量离开作用域时,其值将通过 drop被清理掉,除非数据被移动为另一个变量所有。

在每一个函数中都获取所有权并接着返回所有权有些啰嗦。如果我们想要函数使用一个值但不获取所有权该怎么办呢?如果我们还要接着使用它的话,每次都传进去再返回来就有点烦人了,除此之外,我们也可能想返回函数体中产生的一些数据。这种情况下我们可以使用元组来返回多个值:

fn main() {
    let s1 = String::from("hello");

    let (s2, len) = calculate_length(s1);

    println!("The length of '{}' is {}.", s2, len);
}

fn calculate_length(s: String) -> (String, usize) {
    let length = s.len(); // len() 返回字符串的长度

    (s, length)
}

用官方的话来说这未免有些形式主义,而且这种场景应该很常见。因此,Rust 对此提供了一个功能,叫做 引用references)。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值