Rust简聊 - 所有权的使用方式

所有权

定义

  1. 所有权:指Rust数据的使用权
  2. 所有者:代码里就用变量表示
  3. 作用域:变量有效(valid)的那个代码区间。简单来说就是它定义时所在的那个最里层的花括号括起的部分,从变量创建时开始,到花括号结束的地方

解决问题

通过所有权系统管理内存数据,一方面有效解决数据的并发安全问题,同时编译器在编译时会根据一系列的规则进行检查,避免将错误带到程序运行时

规则

  1. Rust 中的每一个值都有一个 所有者owner)。
  2. 值在任一时刻有且只有一个所有者。
  3. 当所有者(变量)离开作用域,这个值将被丢弃 (所有权生命周期)

并不像 C 语言手动调用 free() 函数去释放堆中的资源

使用方式

rust 复制代码
fn main() {
    let s1 = "hello, world!".to_string();
    let s2 = s1;
    println!("{}", s2);
    println!("{}", s1);  //编译报错,
    //s1赋值后绑定了value的所有权, 将s1给s2赋值后,转移value的所有权给s2,s1将不再可访问
}

Rust 提供了两种权限转移方式,Move & Borrow 。比如租车,没有车的所有权,租来开几天总是可以的。租的行为不发生所有权转变,只是获取临时使用权,这种行为在 Rust 里叫 Borrow 。如果想拥有车的所有权,可以直接购买,买完 4S 店就没有车的所有权了,这种行为在 Rust 里叫 Move

语句 对应含义
let b = a; a绑定的资源转移给b,a不能再使用
let b = &a; a绑定的资源借用给b使用,b只有资源的读权限,a依然能再使用
let b = &mut a; a绑定的资源借用给b使用,b有资源读写权限,a依然能再使用
let mut b = &mut a; a绑定的资源借用给b使用,b有资源读写权限,a依然能再使用;同时b是可变的,可绑定到新的资源上面去

移动还是复制?

  1. 默认做复制所有权(copy)的操作的有 7 种。

    1. 所有的整数类型,比如 u32;
    2. 布尔类型 bool;
    3. 浮点数类型,比如 f32、f64;
    4. 字符类型 char;
    5. 由以上类型组成的元组类型 tuple,如(i32, i32, char);
    6. 由以上类型组成的数组类型 array,如 [9; 100];
    7. 不可变引用类型 &。(&mut 是不支持copy的,因为一个变量在一个时刻内只能有一个可变引用)。
  2. 其余的未实现copy trait的都是move

引用的分类

定义

  1. 不可变引用:&x是对变量 x 的不可变引用,不可以对值进行更改
  2. 可变引用:&mut x是对变量 x 的可变引用,可以对值进行更改

解决问题

  1. 不可变引用:是一种引用,为其他处理逻辑提供上文
  2. 可变引用:既是一种引用,又能够修改指向资源的内容

ex: 引用一个第三方库,它没有把所有权类型暴露出来,但是确实又有更新其内部状态的需求,就需要可变引用

引用生命周期

引用型变量的作用域是从它定义起到它最后一次使用时结束(肯定小于等于所有者的生命周期,否则容易产生悬垂指针)

引用生命周期的关键点

定义

简单说:多个只读引用&交叉无问题,多个可写引用&mut交叉有问题,一个可写引用&mut和一个可读引用&有问题,直接操作所有权的值 = 加一个可写引用

  1. 一个所有权型变量的可变引用 &mut 与不可变引用 & 的作用域不能交叠

    1. 报错:cannot borrow a as mutable because it is also borrowed as immutable

  2. 同一个所有权型变量的可变借用 &mut 之间的作用域也不能交叠

    1. 报错:cannot borrow a as mutable more than once at a time

  3. 在有引用 &/&mut 的情况下,不能对所有权变量进行写操作,只能借用完成(物归原主)才能更新

    1. 报错:cannot assign to a because it is borrowed

  4. 可以同时有多个可读引用 &****

ini 复制代码
fn main() {
  let mut a = 10u32; 
  let c = &a;       //变量c的生命周期由此开始
  let b = &mut a;   //变量b的生命周期由此开始
  *b = 20;          //变量b的生命周期到此结束
  println!("{c}");  //变量c的生命周期到此结束
}
//因此b和c的生命周期发生了交叉,所以发生了编译报错

解决问题

避免多线程条件下读写竞争导致的数据不一致性

相关推荐
幸运小圣1 小时前
Vue3 -- 项目配置之stylelint【企业级项目配置保姆级教程3】
开发语言·后端·rust
老猿讲编程3 小时前
Rust编写的贪吃蛇小游戏源代码解读
开发语言·后端·rust
yezipi耶不耶9 小时前
Rust 所有权机制
开发语言·后端·rust
喜欢打篮球的普通人9 小时前
rust并发
rust
大鲤余13 小时前
Rust开发一个命令行工具(一,简单版持续更新)
开发语言·后端·rust
梦想画家13 小时前
快速学习Serde包实现rust对象序列化
开发语言·rust·序列化
数据智能老司机17 小时前
Rust原子和锁——Rust 并发基础
性能优化·rust·编程语言
喜欢打篮球的普通人19 小时前
Rust面向对象特性
开发语言·windows·rust
上趣工作室21 小时前
uniapp中使用全局样式文件引入的三种方式
开发语言·rust·uni-app
许野平1 天前
Rust:GUI 开源框架
开发语言·后端·rust·gui