当前位置:网站首页>Rust所有权(非常重要)
Rust所有权(非常重要)
2022-07-02 23:31:00 【王紫情大本蛋】
1.其他语言的内存管理,在C/C++中,开发者需要手动释放申请的内存资源。在Java(jvm) 中,JVM采用了垃圾回收的机制,但是这样会降低运行时的效率,并非实时的,所以JVM会尽可能少的回收,这很矛盾,所以还是不好,而 Rust 对栈内存和堆内存一视同仁,超出作用域一律自动释放。Rust 的这个特点在兼顾性能的情况下、有效的减少了代码量和内存泄漏隐患。。
2.Rust所有权规则:每一个值都有一个变量,称为其所有者,一次只能有一个所有者,当所有者不在程序运行范围内的时候,该值将会被删除。
3.变量范围:rust以大括号为界,超出范围则会被回收。申请长度不确定的内存时,会使用到堆这种结构。
4.变量与数据的交互方式:第一种是移动(move),第二种是克隆(clone)。
移动(move): 多个变量可以在 Rust 中以不同的方式与相同的数据交互
let x=3; let y=x;
这里的数据是基本数据类型,所以不需要存到堆中,只在栈中复制和移动。
基本数据类型:
1.所有整数类型,例如 i32 、 u32 、 i64 等。
2.布尔类型 bool,值为 true 或 false 。
3.所有浮点类型,f32 和 f64。
4.字符类型 char。
5.仅包含以上类型数据的元组(Tuples)。
如果发生的情况在堆里面,就会不一样:
let s1=String::from("hello");
let s2=s1;
此处hello需要存在堆里面,后面释放的时候,并不会释放两次,因为s2=s1时,s1已经无效了,后面无法使用。
克隆(clone): 但如果需要将数据单纯的复制一份以供他用,可以使用数据的第二种交互方式。
fn main() {
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
}
这里释放资源的时候,会被当成两个资源释放。
5.函数的所有权机制
fn main() {
let s = String::from("hello");
// s 被声明有效
takes_ownership(s);
// s 的值被当作参数传入函数
// 所以可以当作 s 已经被移动,从这里开始已经无效
let x = 5;
// x 被声明有效
makes_copy(x);
// x 的值被当作参数传入函数
// 但 x 是基本类型,依然有效
// 在这里依然可以使用 x 却不能使用 s
} // 函数结束, x 无效, 然后是 s. 但 s 已被移动, 所以不用被释放
fn takes_ownership(some_string: String) {
// 一个 String 参数 some_string 传入,有效
println!("{}", some_string);
} // 函数结束, 参数 some_string 在这里释放
fn makes_copy(some_integer: i32) {
// 一个 i32 参数 some_integer 传入,有效
println!("{}", some_integer);
} // 函数结束, 参数 some_integer 是基本类型, 无需释放
也就是说,如果函数变量当作参数传入函数,他和移动的效果是一样的。
6.函数返回值的所有权机制
fn main() {
let s1 = gives_ownership();
// gives_ownership 移动它的返回值到 s1
let s2 = String::from("hello");
// s2 被声明有效
let s3 = takes_and_gives_back(s2);
// s2 被当作参数移动, s3 获得返回值所有权
} // s3 无效被释放, s2 被移动, s1 无效被释放.
fn gives_ownership() -> String {
let some_string = String::from("hello");
// some_string 被声明有效
return some_string;
// some_string 被当作返回值移动出函数
}
fn takes_and_gives_back(a_string: String) -> String {
// a_string 被声明有效
a_string // a_string 被当作返回值移出函数
}
被当作函数返回值的变量所有权将会被移动出函数,并返回到调用函数的地方,而不会被无效释放。
7.引用(reference)和租借(borrow)、
引用其实可以当成是指针,是变量的间接访问方式
fn main(){
let s1=String::from("hello");
let s2=&s1;
println!("s1 is {},s2 is {}",s1,s2);
}
这里的s1并不会被无效,s1个地址,它指向堆中的量,s1把地址给s2,s2指向s1。
记住这张图,s2=&s1。。当然在函数中传递引用参数,也是和这里一样的效果。
引用不会获得值的所有权,引用只是租借值的所有权。在引用之后s2=&s1,如果s3=s1,也就是将s1移动到s3,这时s2就无法租借s1而失效,需要重新租借s3。
同时,也不可以租借之后对值进行修改,这个和租房子一个道理,未经房东允许,不可以改变房子。
但是,也可以房东允许你装修:
fn main(){
let mut s1=String::from("run");
let s2=&mut s1;
s2.push_str("oob");
println!("{}",s2);
}
这里的&mut修饰的是可变的引用类型。
提出一个很重要的概念:同时写内存造成数据不一致的问题。
可变引用不允许多重引用,但是不可变引用可以。
let mut s = String::from("hello");
let r1 = &mut s;
let r2 = &mut s;
println!("{}, {}", r1, r2);
这段代码有问题,因为多重可变引用了s。而rust对于这种设计就是出于对并发状态下发生数据访问碰撞的考虑,防止同时写进行修改数据造成数据的不一致性。
8.悬垂引用(dangling reference)
定义:指的是那种没有实际指向一个真正能访问的数据的指针(注意,不一定是空指针,还有可能是已经释放的资源)。这个就是C语言里面说的“野指针”,任何指针变量刚被创建时不会自动成为NULL指针,它的缺省值是随机的,它会乱指一气。所以,指针变量在创建的同时应当被初始化,要么将指针设置为NULL,要么让它指向合法的内存。
在Rust语言里面不允许出现,如果有,编译器会发现它。
边栏推荐
- [golang syntax] map common errors golang panic: assignment to entry in nil map
- Don't want teachers to see themselves with cameras in online classes? Virtual camera you deserve!
- 多进程编程(一):基本概念
- 写论文可以去哪些网站搜索参考文献?
- Luogu_ P2010 [noip2016 popularization group] reply date_ Half enumeration
- 多进程编程(四):共享内存
- Free we media essential tools sharing
- Maya fishing house modeling
- NC24325 [USACO 2012 Mar S]Flowerpot
- Multiprocess programming (I): basic concepts
猜你喜欢
Mutual exclusion and synchronization of threads
Where can I find the English literature of the thesis (except HowNet)?
有哪些比较推荐的论文翻译软件?
【雅思阅读】王希伟阅读P1(阅读判断题)
[IELTS reading] Wang Xiwei reading P1 (reading judgment question)
TypeError: Cannot read properties of undefined (reading ***)
Monitor container runtime tool Falco
pageoffice-之bug修改之旅
Pageoffice - bug modification journey
Hundreds of continuous innovation to create free low code office tools
随机推荐
Shell脚本基本使用
Explain in detail the significance of the contour topology matrix obtained by using the contour detection function findcontours() of OpenCV, and how to draw the contour topology map with the contour t
About the practice topic of screen related to unity screen, unity moves around a certain point inside
Markdown tutorial
NC50528 滑动窗口
论文的英文文献在哪找(除了知网)?
logback配置文件
在线预览Word文档
英文论文有具体的格式吗?
Multi process programming (III): message queue
[shutter] image component (image component introduction | image constructor | image.network constructor | image.asset constructor)
MySQL 23道经典面试吊打面试官
Wechat applet obtains the information of an element (height, width, etc.) and converts PX to rpx.
UART、RS232、RS485、I2C和SPI的介绍
Multiprocess programming (V): semaphores
可下载《2022年中国数字化办公市场研究报告》详解1768亿元市场
Nc50528 sliding window
Pageoffice - bug modification journey
Chapter 4 of getting started with MySQL: data types stored in data tables
【雅思阅读】王希伟阅读P1(阅读判断题)