rust和c最明显的区别就是有所有权系统了,例如

    let mut a = [1, 2, 3];
    let mut b = a;

    println!("a = {:?} addr: {:p}  b = {:? } addr{:p}", a, &a, b, &b);
    a[0] = 2;
    println!("a = {:?} addr: {:p}  b = {:? } addr{:p}", a, &a, b, &b);

打印出来的是

a = [1, 2, 3] addr: 0x23f4eff2f4 b = [1, 2, 3] addr0x23f4eff300
a = [2, 2, 3] addr: 0x23f4eff2f4 b = [1, 2, 3] addr0x23f4eff300

按照c语言的逻辑a 和b都是指向数组的一个指针,但是这里却不是这样的
这里a[0]没有变化是因为 如果rust数组中的类型是实现copy的 那这个数组也默认实现了copy

在 let mut b = a; rust中赋值的时候如果变量实现了copy默认是copy的 如果没有实现才会将所有权转移给b 这里就和c的差异比较大了 并不是把a的地址给b了 而是完整复制了一份a的值

同样的结构体也是这样的

 #[derive(Copy, Clone)]
 struct st_a(i32);


 let mut a = st_a(0);
 let mut b = a;

 println!("a = {:?} addr: {:p} a.0: {:p}  b = {:? } addr{:p} b.0:{:p}", a.0, &a, &a.0, b.0, &b, &b.0);
 a.0 = 2;
 println!("a = {:?} addr: {:p} a.0: {:p}  b = {:? } addr{:p} b.0:{:p}", a.0, &a, &a.0, b.0, &b, &b.0);

打印的是

a = 0 addr: 0xca526ff370 a.0: 0xca526ff370 b = 0 addr0xca526ff374 b.0:0xca526ff374
a = 2 addr: 0xca526ff370 a.0: 0xca526ff370 b = 0 addr0xca526ff374 b.0:0xca526ff374

而如果将这个结构体的
#[derive(Copy, Clone)]
去掉

image.png

就发生了所有权的转移

同理函数的参数也是同样的规则

// #[derive(Copy, Clone)]
struct st_a(i32);

 fn test_st_copy(a: st_a){}


 let a = st_a(0);
 test_st_copy(a);
 let b = a;

也同样报
image.png

同样的设计多线程时候也是适用的,下面的代码也是可以运行的


    let mut a = [1, 2, 3];
    let handle = thread::spawn(move || {
        println!("{:?}", a);
    });
    handle.join().unwrap();
    let mut b = a;

下面的代码是同样的道理

// #[derive(Copy, Clone)]
struct st_a(i32);

    let mut a = st_a(0);
    let handle = thread::spawn(move || {
        println!("{:?}", (&a).0);
    });
    handle.join().unwrap();
    // let mut b = a;  //error[E0382]: use of moved value: `a`


到这里只是涉及所有权的问题 , 但是多线程时候不光所有权的转移 还设计到多线程的同步, 锁也设计到所有权的问题,这样就出现了一些奇奇怪怪的写法,其实就是所有权和并发交叉时候应该的写法

Arc::new(Mutex::new(0));


o_ra
3 声望3 粉丝

记录工作中碰到的问题