Skip to content

rust:copy & move #55

@hello2dj

Description

@hello2dj

move & copy

什么是 move? 什么又是 copy 呢?

  1. copy

    我们以一个好理解的角度入手:那就是我们平时使用的快捷键 Ctrl+C & Ctrl+V 这个就是copy
    image

    如上图 从 a 位置 Ctrl+C 在 b 位置 Ctrl+V,于是 b 位置也有 'C'。原来的 'C',我们还可以继续操作。这个过程就是个 copy。这个叫先感性的理解一下啥是 copy,就是依据一个东西再造一个一模一样的出来,这两个东西共存。3D 打印,完美的 copy。

    那对于 rust 来说 copy 是啥呢?

    1. copy 的语义表现

      资源:可以简单的理解为变量

      将资源 copy 以后,原资源可以继续使用,copy 的新资源也可以使用。

    let a = 32;
    let b = a; // copy
    
    println!("a: {}, b: {}", a, b); // a, b 都可以使用

    我一步一步来分析,看一个最简单的 copy 的使用场景

    let a: i32 = 23;

    上面的一个表达式语句给了我们哪些信息呢?

    • 声明了一个 变量 a
    • a 的类型是 i32
    • a 是不可变的
    • a 的值 是 23
    • a 在栈上分配
    • a 占用的内存大小是 4 个字节
    let a: i32 = 23;
    let b = a;

    这个例子又多了一条表达式语句,那多出来的那条又给了我们什么信息呢?

    • 声明了一个 变量 b

    • b 的类型是 i32

    • b 是不可变的

    • b 在栈上分配

    • b 占用的内存大小是 4 个字节

    • b 的值呢? 肯定是 23

    b 的值 是 23,那 a 的值是如何赋值给 b 的呢?copy 按位 copy 。
    image

    0x00 的内容是 a 的内容,当我们赋值的时候 就会 把 0x00 的内容直接 copy 到 0x02 ( Ctrl+c & Ctrl+v ),这样就完成了 rust 中的一次赋值,也会是 copy。

    1. copy 语义的实现细节: copy by bits

      要解释按位 copy 就需要用到复合类型。

      上面我们讲了 i32 基本类型发生 copy 的场景,接下来我们看看复合类型的copy。

      // 不包含引用的复合类型
      #[derive(Copy, Clone)] // 需要明确这个复合类型可以 copy
      struct A {
      	x: i32,
      	y: i32,
      }
      let a = A { x: 32, y: 34 };
      let b = a; // copy

image

       //  包含引用类型
       #[derive(Copy, Clone)] // 需要明确这个复合类型可以 copy
       struct A<'a> {
     	x: i32,
     	y: &'a i32,
       }
       let y = 377; 
       let a = A { x: 32, y: &y };
       let b = a; // copy

image

     按位 copy 的要点来了,b 的 y 值也是 0x00,并不会 把 y 引用的内容也 copy 一遍。
  1. copy 语义的发生场景

    copy 会发生在以下场景中

  • 变量赋值

    let a = b; // copy
  • 函数传参

    fn say(word: i32) {}
    
    let c = 32;
    
    say(c); // copy
  • 函数返回值

    fn give_you() -> i32 {
    	return 23;
    }
  • 模式匹配 match

    struct A {
    	i: i32
    };
    
    let a = A { i: 32 };
    
    match a {
    	A {i} => println!("###, {}", i); // copy
    };
  • 模式匹配 let

    struct A {
    	i: i32
    };
    
    let a = A { i: 32 };
    
    let A { i: x }  = a; // copy
  • 闭包 capture

    let a = 32;
    let c = vec![1,2,3,4];
    let d: Vec<i32> = c
    	.iter()
    	.map(|v| v + a) // copy a
    	.collect();

Metadata

Metadata

Assignees

No one assigned

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions