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)]
去掉
就发生了所有权的转移
同理函数的参数也是同样的规则
// #[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;
也同样报
同样的设计多线程时候也是适用的,下面的代码也是可以运行的
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));
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。