Rust系列(10):所有权的唯一性和转移
  oS1xgoxjr0QZ 2023年11月02日 32 0

今天学习的内容是 Rust 中的所有权的唯一性和所有权的转移

唯一性

上篇文章介绍了一些所有权的概念,包括:

  • 每个值都有一个对应的变量作为它的所有者,该变量拥有对这个值的所有权。
  • 当变量离开自己的作用域时,它的值就会被回收和释放掉。

关于所有权还有另一个特性,就是同一时间一个值只能有一个所有者。比如这段代码:

fn main() {
  let s1 = String::from("hello");
  let s2 = s1;
  println!("{}", s1);
}

运行这段代码,会报错:

Rust系列(10):所有权的唯一性和转移_Rust

报错信息 borrow of moved value: s1 的意思是变量 s1 的值已经被移动了,导致 s1 现在没有值,所以打印不出来。

正如示例中的 let s2 = s1 ,它的意思是将变量 s1 绑定的值,从 s1 的身上转移到了 变量 s2 的身上,所以 s1 现在没有值了,编译器就会报错。

这就体现了所有权的一个特性:同一时间一个值只能有一个所有者

所有权的转移

还是以这段代码为例:

fn main() {
  let s1 = String::from("hello");
  let s2 = s1;
  println!("{}", s1);
}

这段代码运行会报错,提示变量 s1 的值已经被移动了。

对于 JSer 来说,这有些不易理解。因为如果是按照 JS 中的语法来看,let s2 = s1 就是做了一个赋值操作,将变量 s1 的值赋值给了变量 s2,s1 是可以正常打印的。

而在 Rust 中,这里有两点是和 JS 不同的。一是字符串值属于复杂数据类型,存在堆内存中。二是由于所有权的存在,导致一个值只能有一个所有者。所以在将 s1 的值交给 s2 之后,值的所有者变为了 s2,s1 不再有对值的控制权,所以再打印 s1 就会报错。

这个过程涉及到了一个新的特性,所有权的转移。

Rust 中的复杂数据类型的值,都存在堆内存中。比如:

let s1 = String::from("hello");
let s2 = s1;

第一行代码运行时,会申请一块堆内存空间来存放字符串值,然后将该堆内存的指针地址,赋值给变量 s1,存在栈内存中。

第二行代码,是将变量 s1 所绑定的一个指针地址,转移给了变量 s2,导致 s1 不再拥有对指针地址的所有权。

这个过程就叫所有权的转移。

上面的代码示例中是通过赋值操作,将值的所有权进行了转译。除此之外,函数传参,函数返回等操作也会发生所有权的转移,比如:

fn main() {
  let s1 = String::from("hello");
  // 将变量 s1 对字符串值的所有权转移给了函数 reverse。到这一步,s1 就失去了对值的所有权。
  // 函数 reverse 执行完成,s2 拥有了函数返回值的所有权
  let s2 = reverse(s1);
  println!("{}", s2);
}

// 参数 s 拿到了字符串值的所有权,在函数作用域内可以使用该值
fn reverse(s: String) -> String {
  // 函数通过返回值,又将 s 的所有权转移回去
  s.chars().rev().collect()
}

小结

所有权的唯一性,即同一时刻一个值只能有一个所有者。所有权的规则保证了谁拥有对数据的绝对控制权,从而提高了 Rust 的内存安全性。这是 Rust 不同于其他编程语言的重要特色之一。 所有权的转移,对于一个复杂数据类型的值,在执行赋值操作,函数传参,函数返回等操作时,会将所有权进行转移。


【版权声明】本文内容来自摩杜云社区用户原创、第三方投稿、转载,内容版权归原作者所有。本网站的目的在于传递更多信息,不拥有版权,亦不承担相应法律责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@moduyun.com

  1. 分享:
最后一次编辑于 2023年11月08日 0

暂无评论

推荐阅读
  oS1xgoxjr0QZ   2023年11月02日   42   0   0 数组Rust
  oS1xgoxjr0QZ   2023年11月02日   31   0   0 Rust
  dBFTbkVLMBge   2023年11月02日   29   0   0 Rust
  oS1xgoxjr0QZ   2023年11月02日   39   0   0 Rust
  oS1xgoxjr0QZ   2023年11月02日   25   0   0 Rust
  oS1xgoxjr0QZ   2023年11月02日   41   0   0 Rust
  oS1xgoxjr0QZ   2023年11月02日   48   0   0 Rust
  y5zqVixaDLkE   2023年11月02日   34   0   0 RustmysqlPostgreSQL
oS1xgoxjr0QZ