范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Rust所有权探索

  变量在函数调用过程中的传递fn main() {     let data = vec![5, 7, 3, 1];     let v = 7;      match find_pos(data, v) {         Some(pos) => println!("Found {} at {}", v, pos),         None => println!("{} Not found", v),     } }  fn find_pos(data: Vec, v: u32) -> Option {     for (pos, item) in data.iter().enumerate() {         if *item == v {             return Some(pos);         }     }      None }
  在上面的示例代码中,main()函数定义了一个动态数组data和一个值v,然后将其传递给函数find_pos,在data中查找v是否存在,如果存在则返回v在data中的下标,如果不存在则返回None。
  data 作为动态数组,因为大小在编译期无法确定,所以放在堆上,并且在栈上有一个包含了长度和容量的胖指针指向堆上的内存。
  在调用find_pos函数时,main()函数中的局部变量data和v 作为参数传递给了find_pos(),因此,它们会被放在 find_pos()调用栈中的参数区:
  参数引用
  像Java等大多数编程语言的做饭,现在堆上的内存就有了两个引用,并且每次把data作为参数传递一次,堆上的内存就会多一次引用。
  那么造成的问题就是,无法得知这些引用到底能做什么操作,堆上内存什么时候能够释放,也无法确认。如果有多个调用栈引用堆上的内存时,给内存管理带来很大挑战。同时,引用是可以隐式产生的,随意性太大,例如Java中随处可见的按引用传参,它们可读可写,有很大的权限。
  对于这种堆内存多次引用的问题,传统语言有如下解决方案:C/C++要求开发者手动处理Java等语言使用追踪式GCObjective-C/Swift使用自动引用计数(ARC)
  以上方案,都各有利弊,都是从管理引用的角度来考虑的。
  但是,此问题本质上是因为堆上的内存会被随意引用。所有权和Move语义
  Rust对于值的使用,给出了以下规则:一个值只能被一个变量所拥有,这个变量称为所有者。一个值同一时刻只能有一个所有者。也就是说,不能有两个变量拥有相同的值。所以在变量赋值、参数传递,函数返回等行为,旧的所有者会把值的所有权转移给(Move)新的所有者,保证单一所有者约束。当所有者离开作用域,其拥有的值被丢弃,内存得到释放。一旦所有权转移,之前的变量就不能访问。
  在这三个所有权规则的约束下,上面示例的引用问题可以这样解决:
  所有权和move
  原先main()函数中的data,被移动到find_pos()后,就失效了,Rust编译器会保证main()函数随后的代码无法访问这个变量,就确保了堆上的内存依旧只有唯一的引用。解决了堆上数据的多重引用。
  main()函数中在把data传递给find_pos()后,还想让main()函数能够访问的化,可以调用clone()方法,把data复制一份出来。
  但是这种手动复制,会让代码变得复杂,一些只存储在栈上的简单类型数据,如果要避免所有权转移之后不能访问的情况,只能频繁的手动clone复制。
  Rust给出了两种方案:如果不希望值的所有权被转移,可以让数据结构实现Copy trait,这样在赋值或传参的时候,值会自动按位拷贝(浅拷贝)。Rust在设计的时候,已经保证了无法为一个在堆上分配内存的结构实现Copy。例如String等结构时不能实现Copy的。在这种情况下,如果不希望值的所有权被转移,又无法使用Copy语义,那么可以使用"借用"数据。Copy语义和Copy trait
  符合Copy语义的类型,在赋值或传参时,值会自动按位拷贝。
  如果数据类型没有实现Copy trait,在赋值或者函数调用的时候无法Copy,那么就按默认的Move语义。
  也就是说,要移动一个值,如果值的类型实现了Copy trait,就会自动使用Copy语义进行拷贝,否则使用Move语义进行移动。
  但是Copy trait也有一定的限制,Copy trait和Drop trait 不能共存。一旦你实现了Copy trait,就无法实现Drop trait。反之亦然。实现了Copy trait 的数据结构fn is_copy() {}  fn types_impl_copy_trait() {     is_copy::();     is_copy::();      // 所有的整数类型都是 copy     is_copy::();     is_copy::();     is_copy::();     is_copy::();     is_copy::();     is_copy::();     is_copy::();     is_copy::();     is_copy::();      is_copy::();     is_copy::();      // 函数指针是copy     is_copy::();      // 裸指针是 copy     is_copy::<*const String>();     is_copy::<*mut String>();      // 不可变引用是 copy     is_copy::<&String>();     is_copy::<&[Vec]>();      //对于数组/元组,如果其内部类型是 copy,那么它们就是 copy     is_copy::<[u8; 4]>();     is_copy::<(&str, &str)>(); } fn types_not_impl_copy_trait() {     // DST 类型不是 copy     // is_copy::();     // is_copy::<[u8]>();      // 有堆内存的类型不是 copy     //is_copy::>();     //is_copy::();      //可变引用不是 copy     //is_copy::<&mut String>();      // 对于数组/元组,如果其内部类型不是 copy,那么它们也不是copy     //is_copy::<[Vec;4]>;     //is_copy::<(String,u23)>(); }原生类型(函数、不可变引用、裸指针)实现了Copy。数组和元组,如果其内部的数据结构实现了Copy,那么它们也实现了Copy。可变引用没有实现Copy。非固定大小的数据结构,没有实现Copy。Borrow语义
  Borrow语义通过引用语法(&或者&mut)来实现。
  在Rust中,"借用"和"引用"是一个概念。所有的引用都只是借用了"临时使用权",它并不破坏值的单一所有权约束。
  在默认的情况下,Rust的借用都是只读的。只读借用
  本质上,引用是一个受控的指针,指向某个特定的类型。
  其他传统语言,函数传参有两种方式:传值(pass-by-value)和 传引用(pass-by-reference)。
  比如在Java,给函数传一个整数,这是传值,与Rust中的Copy语义一致。
  给函数传一个对象,或者是任何堆上的数据结构,Java会自动隐式地传引用。
  但是Java的引用是对象的别名,这也导致随着程序的运行,同一块内存的引用到处都是,不得不依赖GC进行内存回收。
  Rust中没有传引用的概念,Rust所有的参数传递都是传值,不管是Copy还是Move。
  所以,在Rust中,必须显式地把某个数据的引用,传给另一个函数。
  Rust的引用实现了Copy trait,所以按照Copy语义,此引用会被复制一份交给要调用的函数。
  对这个函数来说,它并不拥有数据本身,数据只是临时借给它使用。所有权还在原来的拥有者那里。
  在Rust里,引用是一等公民,和其他数据类型地位相等。fn main() {     let data = vec![1, 2, 3, 4]; // data 的生命周期比sum()中对data的引用要长     let data1 = &data; // 借用不能超过值的生存期                        // 值的地址是什么?引用的地址又是什么?     println!(         "address of value: {:p}({:p}),address of data: {:p},data1: {:p}", //0x8aa19bf8a8(0x8aa19bf8a8),address of data: 0x8aa19bf948,data1: 0x8aa19bf8c0         &data,                                                            //0x8aa19bf8a8         data1,                                                            //0x8aa19bf8a8         &&data,                                                           //0x8aa19bf948         &data1                                                            //0x8aa19bf8c0     );      println!("sum of data1: {}", sum(&data)); // sum 函数处在 main() 函数下一层调用栈中,它结束后main函数还会继续执行      // 堆上数据的地址是什么     println!(         "address of items:[{:p},{:p},{:p},{:p}]", //address of items:[0x1cc59705670,0x1cc59705674,0x1cc59705678,0x1cc5970567c]         &data[0],                                 //0x1cc59705670         &data[1],                                 //0x1cc59705674         &data[2],                                 //0x1cc59705678         &data[3],                                 //0x1cc5970567c     ); }  fn sum(data: &[u32]) -> u32 {     //值的地址会改变吗,引用的地址会改变吗     println!(         "address of value: {:p},addr of ref: {:p}", //address of value: 0x1cc59705670,addr of ref: 0x8aa19bf6d0         data,                                       //0x1cc59705670         &data                                       //0x8aa19bf6d0     );     data.iter().sum() }  // 只读引用 实现了 Copy trait,也就意味着引用的赋值、传参都会产生新的浅拷贝 // 虽然data 有很多只读引用指向它,但是堆上的数据依旧只有data 一个所有者:值的任意多个引用并不影响所有权的唯一性。
  借用
  data1、&data和传到sum()里的data1" 都是指向data本身,这个值的地址是固定的。但是它们引用的地址都是不同的。这是因为 只读引用实现了Copy trait,也就是意味着引用的赋值、传参都会产生新的浅拷贝。堆上数据依旧只有data一个所有者。值的任意多个引用并不影响所有权的唯一性。借用的生命周期
  借用(引用)不能超过(overlive)值的生存期。
  堆变量的生命周期不具备任意长短的灵活性,因为堆上内存的生死存亡,跟栈上的所有者牢牢绑定。而栈上内存的生命周期,又跟栈的生命周期相关,所以,我们只需要关心调用栈的生命周期。可变借用/引用
  为了保证内存安全,Rust对可变引用的使用做了严格的约束:在一个作用域内,仅允许一个活跃(真正被用来修改数据的)的可变引用。在一个作用域内,活跃的可变引用(写)和只读引用(读)是互斥的,不能同时存在。就像并发下数据的读写互斥。一个值可以有多个只读引用。引用的生命周期不能超出值的生命周期。

不必过分追求补肾,生活中注意这些小细节能够护肾!现代社会中,大家崇尚的养生理念都是补,殊不知补过了头不仅起不到防病治病的作用,反而有可能加重身体的负担,带来健康问题。补肾也是一样,从中医的角度来讲,肾并不是指肾脏这个器官,而是包郎朗真是捡到宝了!38岁吉娜穿一身红礼服美到国外,身材太惊艳一套成功的造型,我们要考虑的点是非常多的,场合肤色款式身材等等,都是我们需要考量的要素。身材肤色都相对是比较固定的,至少在一个比较长的区间内都是固定的,而场合是在不断的变化当中的,姜妍在花样姐姐中,身材压过林志玲,颜值高过金晨在花样姐姐第二季中,邀请了林志玲,宋丹丹,王琳,姜妍,金晨五位女明星。这档节目就是以五位女星,与三位年轻男明星之间的互动,作为看点。这是东方卫视引进韩国tvN电视台节目花样姐姐,进新小美人鱼哈莉贝莉穿粉色比基尼秀性感身材,出演Ariel梦想成真小美人鱼明星哈莉贝莉(HalleBailey)海滩度假坐在摇椅秋千上摆POSE,身着粉红色比基尼引起轰动周一,哈莉贝利(HalleBailey)在Instagram上展示了她在摇椅乡村爱情中身材巨好的美女,说话嗲声嗲气,胜过关婷娜乡村爱情是一部很有争议的农村题材电视剧,喜欢的人非常喜欢,疯狂追剧,每一集都不落不喜欢的人那是真不喜欢,直言这是一部极其无聊的电视剧。乡爱来了就是年,每到年底,咱们屯里的人的旋律就读懂自己读懂人就读懂了成功!我们经常说四十不惑五十知天命,指的是一个成熟的人,五十岁前就清楚这辈子能不能成功。在五十岁前成功的人,一定读懂了人间这部大书的人,这部书并非人人能看懂,不是会看字就会看懂。更多的人教育意义的黑色童话,突然理解了许嵩的那首胡萝卜须成年后第一次再看童话,没想到竟然是胡萝卜须这样的一本黑色童话。什么是黑色童话?是带着悲观对现实世界的无声控诉,以及对美好事物的质疑,体现了对社会现状的不满,意在告诉大家现实生活不是马思纯瘦了真自信,穿圆领格纹外套搭黑色阔腿裤,显高又时髦!头条创作挑战赛娱乐圈中的女明星们将身材管理看得比较重要,因为当下大众们的审美还是瘦一点儿更好看,上镜的效果也会更好。这不,之前有点发福的马思纯,最近也是瘦回来了,变得越来越自信,穿三月流焱你要像花儿一样,无论身在何处,活出自己的精彩你要像花儿一样,无论身在何处,不管周遭环境如何,都依然潇洒的绽放自己的美丽,活出自己的精彩。Youshouldbelikeaflower,nomatterwhereyouare,n3岁男童反复呕吐被确诊癌症晚期!推荐儿童肿瘤洗澡自查方法日前,湖南省衡阳市,小瑞因反复发烧呕吐不爱走路后被查出患神经母细胞瘤M期高危组(俗称儿童癌症之王)。神经母细胞瘤(NB)是婴幼儿最常见的颅外实体肿瘤,占儿童恶性肿瘤的810。作为颅制作方法只有3个步骤的香菇蒸虾盏教程来啦!香菇蒸虾盏中的虾肉含有丰富的蛋白质和钙质,有利于提高准妈妈的免疫力。香菇含有六大酶类的40多种酶,可以纠正人体酶缺乏症香菇中的脂肪所含脂肪酸,对人体降低血脂有益。宝宝云推荐人群备孕
在成渝经济圈,除重庆成都两个大城市外,你认为谁会成为第三城?这里是优质教育领域创作者Maple老师谈教育,为您解答。随着西部大开发战略实施以来,西部涌现了两座超大型城市成都和重庆,构成成渝经济圈,排名全国第四。至于圈内第三城,呵呵能代表所有未来三年,重庆市平均房价会降到1万以下吗?近几个月以来,重庆的房价出现了下降的态势。目前,重庆市平均房价约为1。2万元,未来三年内,重庆市房价可能会降到1万元以下。为什么这么说呢?总结如下国家对房地产的大政方针是房子是用来重庆和南京相比,哪个城市的综合实力强?你怎么看?南京和重庆相比,论综合实力,肯定重庆胜出。重庆是直辖市,行政级别高于南京。重庆是国家五大中心城市之一,国家的重视程度重于南京。重庆地处中国大后方,是长江上游经济中心,是中西结合部的成都重庆昆明贵阳,西南4大省会城市买房,哪个潜力更大?肯定是成都。成都被誉为天府之国美丽城市,气候宜人,地势平坦,为著名的成都平原,千年古都,名胜古迹,秀丽风景,为世界之旅游城市,亦为国内少有。成都古蜀桑蚕丝绸茶玉,瓷等千年传承,千年农村俗语说牛下麒麟猪下象,这个有什么根据?牛下(农村俗语,就是生产的意思,下文不再解释)麒麟猪下象这句话在民间已经流传千年了,原本的意思只是一个文化含义上的概念,但后来逐步被人认为是一个物种生育现象。它的意思是那些有德行有在深圳月薪1。5万是什么水平?深圳作为我国最发达的城市之一,也是目前我国工资水平最高的三个城市之一,仅次于北京和上海。因此在很多人的眼中,深圳的工资应该很高才对,走在大街上月薪两三万的一抓一大把,但那这只不过是嫁到中国的越南女人都跑光了,这是为什么?嫁到中国的越南女人都跑光了,这是为什么呢?仔细想想,原来她们并非嫁鸡随鸡,嫁狗随狗,嫁个扁担横着走,而是嫁给了孔方兄。现在,在这里孔方兄不是像她们刚嫁过来那些年那么热情似火了,而是不是济南的户口可以在济南买房吗?济南限购政策1本市户籍家庭已拥有一套住房或有住房贷款记录的,申请住房贷款均视为第二套住房贷款,首付比例提高至60。其中商业按揭贷款最长年限缩短至25年,公积金贷款利率执行基准利率的濮阳市未来五年的房价走势会怎样?濮阳在未来五年的房价应该还是呈现稳步上涨趋势!先来看下濮阳现在的房价是多少濮阳的房价,在过去的一年里,涨幅还是比较大的,说明濮阳的房地产市场还是比较火爆的。下面来看一下濮阳的人均收公务员已经32年工龄了,年龄五十岁,该提前退休吗?按照规定,男性公务员60岁退休,也可以选择工龄满30年退休。题主目前已经50岁了,工龄兵龄32年,符合提前退休条件。有没有必要选择提前退休?关键是要看题主家庭经济情况生活向往工作热武警边防和公安边防之间有什么区别和联系?2018年之前,武警边防和公安边防是一块牌子两种称呼,属于现役部队。2018年机构改革的时候,按照军是军警是警的要求,边防部队全体划转到国家移民管理局进行管理,成为了人民警察。先介