在线时间:8:00-16:00
迪恩网络APP
随时随地掌握行业动态
扫描二维码
关注迪恩网络微信公众号
目前仅看了第二版的官方文档,记录一下初步印象,应该还有更深刻一致的解释,水平有限,仅供参考。 初步印象
R非常重视并发,根据官方介绍:Rust 是一门着眼于安全、速度和并发的编程语言。而并发需要解决的就是数据竞争问题,自然会非常重视数据的使用过程,说是小心翼翼不为过。因为数据要关联到有名变量才能使用,所以rust在语言层面上针对变量的使用引入了解决方法,主要涉及的语法有:
需要注意的是,所有权仅针对复杂类型变量(在语法上,是没有copy trait的类型),例如String、vect等在堆上存储数据的类型,而简单类型并不用考虑,如int、tuple、array等,原因就在于赋值时数据是如何拷贝的(虽然都是浅拷贝)。 如果熟悉浅拷贝、深拷贝的概念,自然了解,对于在堆上分配空间的复杂类型,浅拷贝会导致两个或更多变量/指针同时指向同⼀数据,若有变量/指针作写入操作,就会引起数据竞争问题。 所以,Rust用可变/不可变、所有权、生命期等来破坏数据竞争的条件,而这些解决方案全部在编译期搞定! 基本概念1. 不可变、可变let x = 3; // x 默认不可变 x = 4; // 错误! let x = 4; // 正确!遮盖了原有的同名变量 let mut y = 3; // y可变 y = 4; // 正确! 2. 所有权转移(move)fn test(v: String) { println!("fn: {}", v); } // 函数 let x = String::from("hello"); // 所有者x(String类型) let y = x; // 数据的所有权转移给y! let z = x; // 错误!x已不可用 test(y); // 所有权转移,新的所有者是形参v!当函数执行完毕,v离开作用域时值被丢弃(drop)! println!("var: {}", y); // 错误!y已不可用 这难免有令人抓狂的感觉,还能不能愉快地玩耍了?这数据跑得跟兔子一样,想用的时候都不知道去哪了!还可能无意中跑到函数里直接躺尸! 3. 借用/引用(borrow)那么,一个变量想多次使用怎么办?答案是可以借用:使⽤其值但不获取其所有权。 fn test1(v: String) { println!("fn: {}", v); } fn test2(v: &String) { println!("fn: {}", v); } // 参数为引用类型 let s = String::from("hello"); // 所有者s(String类型) let s1 = &s; // 不可变借用(borrow)! let s2 = &s; // 借用 let s3 = s1; // 借用 test2(s1); // 借用 test1(*s1); // 错误!借用者s1没有所有权,无法通过s1转移(cannot move out of borrowed content)。 println!("var: {}", s); // 正确 小结:个人感觉,所有权转移主要为并发服务,本身并不常用,毕竟数据经常要复用,没人乐意要一直提防着数据跑哪去了,尤其在函数调用时。既然如此,一般把所有者保持不变,多使用引用,主要体现在复杂数据结构和函数上。 进一步但是,实际使用的情况会比较复杂,即是否可变与转移、借用三者相互影响(混用)的情况。 首先,是否可变和所有权没有关系。 let x = String::from("hello"); let mut z = x; // 转移后变量x不可用 z.push_str(" z"); //正确 // 可变引用要用星号来获得引用的内容,不可变引用不需要。 let mut x = 5; let y = &mut x; *y += 1; 虽然不可变引用(&T)没有所有权,不会导致值被误转移,但借用之时要求值不能变,这意味着此时:所有权不能转移、所有者不能改值、不能同时有可变引用! let mut x = String::from("hello"); let y = &x; // 不可变引用 let z = x; // 错误 x.push_str(" x"); // 错误 let z = &mut x; // 错误:可变引用 可变引用(&mut T)可变引用使用上略复杂,概念上也没有太统一的理解,这里单独考查。 注:官方文档里没有可变权的概念,但个人感觉,用这个概念比较好理解可变引用的使用,也许还有更本质的解释,特此说明。 可变权move的两种方式 let mut x = String::from("hello"); // 所有者x有可变权 // 1. 直接转移 let y = &mut x; // 1. y为可变引用,可变权move自x let z = y; // 直接转移。z为可变引用 y.push_str(" y"); // 错误!y的可变权已move给z z.push_str(" z"); // 正确 // 2. 间接转移 let mut y = &mut x; // 2. y为可变引用,可变权move自x let w = &mut y; // 要求y可变。w为可变引用 w.push_str(" w"); // 正确 // 转移(函数) fn test(i: &mut String) { i.push_str(" i"); // 正确 } let mut x = String::from("hello"); // 所有者x有可变权 test(&mut x); x.push_str(" x"); // 正确!可变权已归还 可变引用若有写入操作则要求所有者可变。 let x = String::from("hello"); // x不可变 let mut z = &x; // z为不可变引用 z.push_str(" z"); // 错误! let w = &mut z; // w为可变引用 w.push_str(" w"); // 错误! let mut y = x; // 所有权转移,y可变 let z = &mut y; // z为可变引用,要求y可变 z.push_str(" z"); // 正确! let w = &z; // w 为不可变引用 w.push_str(" w"); // 错误! 总结:因为都涉及到值的修改,可变引用的行为和所有者相似,而且可变权和所有权都是面向数据且唯一的。 所有者
可变引用(&mut T)
作者:amita
来源:51CTO
|
2023-10-27
2022-08-15
2022-08-17
2022-09-23
2022-08-13
请发表评论