上一节我们快速浏览了函数及控制结构,加上1.4节的数据类型,是不是跃跃欲试,想大干一场了呢?哈哈,脚印还得一个一个踩,我们今天还得说一说rust的一个重要概念-- 所有权。
我们先不讲所有权概念,先来看一个例子,有什么问题,再看看主流语言都是怎么解决这些问题的,有什么痛点,再来看rust的解决方法,就水到渠成,能更好地理解了。
考虑一个查找函数:(力扣高手勿喷 )给一个数组和一个目标值,用循环遍历数组找出等于目标值的元素索引。
fn main() {
let data = vec![10, 42, 9, 8];
let v = 42;
if let Some(pos) = find_pos(data, v) {
println!("Found {} at {}", v, pos);
}
}
fn find_pos(data: Vec, v: u32) -> Option {
for (pos, item) in data.iter().enumerate() {
if *item == v {
return Some(pos);
}
}
None
}
在C++中,find_pos是传了一个数组的引用,所以堆上数组还是只有一份,只是引用计数+1了(浅拷贝),而多个调用就会出现多个引用,这些引用是通过专门维护引用的代码来管理的,运行时会带来一定的性能损耗。
在java中,GC是通过追踪式定时查看哪些内存标记不使用了,就会清理掉,同样也会带来运行时性能损耗。
我们可以看出,主流语言都会有一些问题。那rust有什么好方法吗?
有,rust借鉴了C++的move语义,配合使用所有权,高效、优美地解决了以上问题,下面我们来看rust是怎么做到的:
fn main() {
let data = vec![10, 42, 9, 8]; //data是数组的所有者
let v = 42;
if let Some(pos) = find_pos(data, v) { //data在函数调用时,把所有权移动给函数data`,data自动失去数组所有权,编译器会阻止后续代码访问data
println!("Found {} at {}", v, pos);
}
}
fn find_pos(data: Vec, v: u32) -> Option { //函数作用域开始,data`拥有数组所有权
for (pos, item) in data.iter().enumerate() {
if *item == v {
return Some(pos);
}
}
None
}// 函数作用域结束,data`被丢弃,堆内存被释放
我加了注释,你们应该很容易能看明白,rust通过move移动语义把数组所有权交给了函数参数,在函数里data`拥有数组的所有权,而函数结束时数组也被安全释放。
这里没有使用多个引用,也不用在运行时再去管理引用计数或者定时清理标记未使用内存块,而是在编译期就安全的管理了堆内存。这就是rust优秀的内存管理之一,优雅、高效。只要能编译通过,rust程序一般而言都不会有什么问题,所以我们很多时候都是在和编译器作斗真
来看看rust所有权三大原则:
所有权虽然很好的解决了多重引用、引用计数管理以及运行时定时检查内存的问题,但是也规定了一个时刻只能有一个变量拥有值,那像上个例子,若我们程序功能要求在函数传参后,需要继续使用原data,还想要使用它指向的数组呢?
这就要用到clone()函数,她可以把数组在内存拷贝一份,然后传回新数组地址给函数调用(深拷贝):
fn main() {
let data = vec![10, 42, 9, 8];
let v = 42;
if let Some(pos) = find_pos(data.clone()), v) { //传值给函数的是clone()的新数组,原data可继续使用,编译器不会报错
println!("Found {} at {}", v, pos);
}
}
fn find_pos(data: Vec, v: u32) -> Option { //clone的数组所有权在data`
for (pos, item) in data.iter().enumerate() {
if *item == v {
return Some(pos);
}
}
None
} //data`离开作用域,clone的数组失效,堆内存被正确释放
当然,如果有需求需要多次clone(),这样深拷贝多个堆数据也不高效,还会用到下一节要说到的copy和borrow等语法。
好了,我们学习了rust很重要的所有权概念,知道了他解决了什么问题,为什么要这么设计,还对比了rust和主流语言的内存管理机制,相信你已经更好理解了所有权,我觉得写rust程序越写越能养成好习惯,因为编译器会不停地督促我写出更健壮的代码 对于今天的内容你有什么看法呢?欢迎在评论区留言讨论!如果觉得文章有用,记得点赞关注加收藏,以后就会第一时间收到文章推送啦 :D
本文由ByteBunny原创,欢迎关注,带你一起长知识!
页面更新:2024-04-10
本站资料均由网友自行发布提供,仅用于学习交流。如有版权问题,请与我联系,QQ:4156828
© CopyRight 2008-2024 All Rights Reserved. Powered By bs178.com 闽ICP备11008920号-3
闽公网安备35020302034844号