Rust基础02-所有权规则、内存与分配

所有权规则

  1. 每个值都有一个变量,这个变量是该值的所有者
  2. 每个值同时只能有一个所有者
  3. 当所有者超出作用域(scope)时,该值将被删除

变量作用域

Scope 就是程序中一个项目的有效范围

fn main() {
    //s 不可用
    let s = "hello";//s 可用
    			   //可对 s 进行相关操作
} //s 作用域到此结束,s 不再可用

String 类型

字符串字面值:程序里手写的那些字符串,它们是不可变的

String类型:在Heap上分配,能够存储在编译时未知数量的文本

  • 创建 String类型 值

    可以使用 from 函数从字符串字面值创建出 String 类型

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

    其中,"::" 表示 from 是 String 类型下的函数,这类字符串是可以被修改的

String类型能够修改,字符串字面量不能修改,这是因为它们的存储方式不同

内存和分配

  • 字符串字面值:

    在编译时就知道它的内容,其文本内容直接被硬编码到最终的可执行文件中

    速度快、高效、不可变性

  • String 类型:

    支持可变性,在Heap上分配内存来保存编译时未知的文本内容

    • 操作系统必须在运行时请求内存

      此步通过调用 String::from 来实现

    • 当用完 String 后,需要使用某种方式将内存返回给操作系统

      String操作

      但Rust采用了不同的方式:对于某个值来说,当拥有它的变量走出作用范围时,内存会立即自动的交还给操作系统

      当变量走出作用域,Rust会自动调用 drop 函数

  • 移动(Move):

    1. 普通情况

      多个变量可以于同一个数据使用一种独特的方式来交互

      let x = 5;
      let y = x;
      

      整数是已知且固定大小的简单的值,这两个5被压入Stack中

    2. String 版本

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

      一个String由三部分组成:

      • 一个指向存放字符串内容的内存的指针

      • 一个长度

        长度len,就是存放字符串内容所需的字节数

      • 一个容量

        容量capacity,指String从操作系统总共获得内存的总字节数

      String类move

      以上三部分放在 Stack 上,存放字符串内容的部分在 Heap 上

      当把 s1 赋给 s2,String 的数据被复制了一份:

      • 在 Stack 上复制了一份指针、长度、容量

      • 并没有复制指针所指向的 Heap 上的数据

      s1赋值于s2

      当变量离开作用域时,Rust 会自动调用 drop 函数,并将变量使用的 Heap 内存释放

      当s1、s2离开作用域时,它们都会尝试释放相同的内存:

      这会引起严重的BUG:二次释放(double free)bug

      因此,Rust为了保证内存安全

      1. Rust 没有尝试复制被分配的内存

      2. Rust 让 s1 失效,当 s1 离开作用域时,Rust不需要释放任何东西

      浅拷贝与深拷贝

      引申:浅拷贝与深拷贝

  • 克隆(Clone):

    若有意对 Heap 上的 String 数据进行深度拷贝,而不仅仅是 Stack 上的数据,可以使用 clone 方法

    这种方法较为耗费资源且针对 Heap 上的数据进行操作

    clone

  • 复制(Copy):对 Stack 上的数据进行操作

    Copy trait,可以用于像整数这样完全存放在 Stack 上的类型

    • 如果一个类型实现了 Copy 这个 trait,那么旧的变量在赋值后仍然可用

    • 但若一个类型或该类型的一部分已实现了 Drop trait,那么 Rust 不允许让它再去实现 Copy trait 了

    任何简单标量的组合类型都可以是 Copy 的,任何需要分配内存或某种资源的都不是 Copy 的

    一些拥有 Copy trait 的类型:

    • 所有的整数类型,例如 u32
    • 布尔类型
    • 字符类型
    • 所有的浮点类型,例如 f64
    • 元组,如果其所有的字段都是 Copy 的

posted on 2022-03-15 22:28  Baby091  阅读(124)  评论(0编辑  收藏  举报

导航