当前位置: 首页 > 科技观察

初识Rust语言的所有权概念_0

时间:2023-03-15 19:20:47 科技观察

目前只看了第二版的官方文档,记录一下初步印象。应该有更深刻和一致的解释。水平有限,仅供参考。实验环境:ubuntu17.10、rust1.18、vscode1.14+extendedrust(rls)。顺便说一句,环境搭建出奇的顺利。Rust工具链简洁美观,原生支持git。安装只需要一条命令:curlhttps://sh.rustup.rs-sSf|嘘。初步印象数据竞争主要有以下三种情况:两个或多个指针同时访问同一个数据。至少写了一个指针。没有同步数据访问的机制。R非常重视并发性,根据官方介绍:Rust是一门注重安全、速度和并发性的编程语言。并发需要解决数据竞争的问题。自然会非常重视数据的使用,说谨慎一点也不为过。因为数据只有在与命名变量相关联时才能使用,所以Rust引入了一种在语言级别使用变量的解决方案。涉及到的主要语法是:当一个变量被声明时,它是不可变的(immutable,default),可变的(mutable)变量赋值当转移所有权(move)和借用(borrow)时,需要注意的是所有权只针对复杂类型variables(语法上,没有copytraits的类型),比如String,vect等堆上存储数据的类型,而Simple类型则不需要考虑,比如int,tuple,array等。原因是如何数据在赋值时被复制(尽管它们都是浅拷贝)。如果熟悉浅拷贝和深拷贝的概念,自然会明白,对于在堆上分配空间的复杂类型,浅拷贝会导致两个或多个变量/指针同时指向同一个数据。如果有变量/指针要写,导致数据竞争问题。所以Rust用mutable/immutable、ownership、lifetime等来破坏datarace的条件,而这些解决方案都是在编译期完成的!当然,代价是很难快速验证想法。毕竟,在使用变量时一定要小心,否则你将无法对其进行编辑。我期待最佳实践和IDE支持。基本概念1.不可变,可变letx=3;//x默认不可变x=4;//错误!让x=4;//正确的!覆盖原来的同名变量letmuty=3;//y变量y=4;//正确的!2.所有权转移(move)fntest(v:String){println!("fn:{}",v);}//函数letx=String::from("hello");//所有者x(字符串类型)lety=x;//数据的所有权转移给y!让z=x;//错误!x不再可用test(y);//所有权转移,新的所有者是形参v!当函数完成执行时,当v超出范围时,该值将被丢弃!println!("var:{}",y);//错误!y不在了,难免会觉得抓狂,还能玩的开心吗?这个数据跑的跟兔子似的,想用的时候不知道跑到哪里去了!也有可能一不小心跑到函数里直接躺下!3.借用/引用(borrow)那么,要多次使用一个变量怎么办呢?答案是它可以被借用:使用它的价值而不取得它的所有权。fntest1(v:String){println!("fn:{}",v);}fntest2(v:&String){println!("fn:{}",v);}//参数是引用类型lets=String::from("hello");//所有者s(字符串类型)让s1=&s;//不可变借用(借用)!让s2=&s;//借用lets3=s1;//借用test2(s1);//借用test1(*s1);//错误!借用者s1没有所有权,不能通过s1转让(不能搬出借用的内容)。println!("var:{}",s);//正确总结:个人感觉所有权转移主要针对并发服务,不常用。毕竟数据经常被重用,没有人愿意时刻提防数据去向Go,尤其是在函数调用上。既然如此,owner一般保持不变,引用较多,主要体现在复杂的数据结构和函数上。然而,进一步的,实际使用情况会更加复杂,即是否可变、转让、借用的相互影响(混合使用)。从数据竞争的角度看:读和读不冲突,但是读和写、写和写会冲突(读不可变,写可变);从实现的角度来看:引用是基于所有权的。因此,可以看出哪些对象会发生冲突:(owner,reference)×(immutable,mutable)首先,是否可变与所有权无关。让x=String::from("你好");让mutz=x;//传递后变量x不可用z.push_str("z");//正确//mutablereferencesshouldbeobtainedwithaasterisk引用的内容,不可变引用不需要。让mutx=5;让y=&mutx;*y+=1;不可变引用(&T)虽然没有所有权,不会导致价值被错误转移,但是借用时价值不能改变,这时意味着:所有权不能转移,所有者不能改变价值,以及不能同时有可变引用!让mutx=String::from("hello");让y=&x;//不可变引用letz=x;//错误x.push_str("x");//错误让z=&mutx;//Error:variablereferencevariablereference(&mutT)变量引用使用起来稍显复杂,概念上也没有统一的理解,这里单独考察一下。“变量权”是指变量引用对数据的读写权限,具有唯一性(只有一个变量引用可用)和排他性(其他读写均无效),因此对编译有相当大的影响。可变引用的可变权限类似于所有者对数据的所有权,因为可变权限也具有移动行为。注:官方文档中并没有变量权限的概念,但个人觉得还是用这个概念来理解变量引用的使用比较好,可能会有更本质的解释,特此说明。变量右移的两种方式letmutx=String::from("hello");//所有者x拥有变量权//1.直接转移lety=&mutx;//1.y是变量变量引用,变量权重从xletz=y;//直接传输。z是变量引用y.push_str("y");//错误!y的变量right已移至zz.push_str("z");//正确//2.间接传递letmuty=&mutx;//2.y是变量引用,变量right从xletw=&muty;//要求y是可变的。w是可变引用w.push_str("w");//正确//transfer(function)fntest(i:&mutString){i.push_str("i");//正确}letmutx=String::from("hello");//所有者x具有可变权限test(&mutx);x.push_str("x");//正确的!返回可变权利。如果有写操作,可变引用需要可变所有者。让x=String::from("你好");//x是不可变的letmutz=&x;//z是一个不可变引用z.push_str("z");//错误!让w=&mutz;//w是一个可变引用w.push_str("w");//错误!让muty=x;//所有权转移,y是可变的letz=&muty;//z是一个可变引用,要求y是可变的z.push_str("z");//正确的!让w=&z;//w是一个不可变引用w.push_str("w");//错误!总结:可变引用与所有者的行为类似,因为它们都涉及值修改,并且可变权限和所有权都是面向数据且唯一的。所有者拥有所有权,移动后不再可用。当所有者生命周期结束时,该值将被丢弃。它类似于读取时的不可变引用,写入时的可变引用。可变引用(&mutT)具有可变权限,可以从引用的对象中移动。当可变引用的生命周期结束时,可变权限自动归还。可变权利的来源应该来自所有者,否则意义不大。参考Rust环境配置项列表官方文档:RustProgrammingLanguage(第二版)Rust教程的归属11你在开发过程中遇到过哪些Rust陷阱?