Rust,再次入门
前言
Rust是一个别扭的语言,他引入了一些概念使得程序变得安全,
https://www.bilibili.com/video/BV1bVS4YXEE5
所有权
rust中,由Box包装的变量具有所有权。
所有权的设计意义在于避免手动管理内存。函数内创建的Box变量,会在函数生命周期结束时自动释放内存。而如果不设计所有权,这个内存地址会被释放多次,导致程序崩溃。
比如first有所有权,当执行let second = first;
时,所有权会转移到second上,后续代码不能再使用到first变量。
而如果是js,first和second都会获得对象的引用,二者等效。
如何转移?
理论上来说,赋值会引起所有权转移,而函数传参本身是一种赋值(实参赋值给形参)。
所以,有两种明显的所有权转移方法。
- 直接赋值
- 传入函数
fn main() {
let first = String::from("Ferris");
let full = add_suffix(first);
// 数据的所有权转移到了full身上,first失效,因此会报错
println!("{full}, originally {first}");
}
fn add_suffix(mut name: String) -> String {
name.push_str(" Jr.");
name
}
所以我认为,所有权的转移如下:
first -> name(函数内部参数) -> full
引用和解引用
当使用Box创建对象时,会在堆内存上开辟内存空间(Heap),栈内存上是内存的指针。
因此,从指针到数据之间,使用解引用来获取数据。
fn main() {
let mut x: Box<i32> = Box::new(1);
// 比如下面*x是简单数据1,因此直接存在栈内存上
let a:i32 = *x;
// *x直接访问x对应的数据,因此可以直接+=改变其值
*x += 1;
println!("x为:{x},a为:{a}");
let r1: &Box<i32> = &x;
let b: i32 = **r1;
// &*x可以理解为&(*x),即对Heap上数据的直接引用。
// 在rust中这被称为借用,目的是为了和拥有所有权的x区分开。
// 由于只有box会释放内存,因此多个引用并不会引发多次释放内存的问题
// 所以依然是安全的
let r2:&i32 = &*x;
let c:i32 = *r2;
println!("转移?:{x},a为:{a}");
}
这部分和c语言差不多。
题目
1
3次,上面L1这张图就是解析。
2
答案是第三个,因为传入函数的是&v,而&v不具有所有权,所以不会引起内存释放等问题。
例子
当执行v.push(4)时,重新分配了内存并放在了一个新的地址,然后让v指向这个地址。
然而,num依然指向原来的地址,因此引发错误。
结论
确实挺难的,太束手束脚了,感觉很痛苦。