Rust中的GC

“GC”的新姿势 – ownership> 编程语言中的“垃圾回收”的本质:找到并回收不再被使用的内存空间

不要动,让我来

JAVA语言中不需要手动去处理内存回收的问题, 虚拟机有完善的垃圾回收机制,成熟的动态内存分配和回收
阿里妹妹推的JVM GC文章

Talk is cheap. Show me the code.

C语言中需要手动分配,手动释放内存空间,自己的屁股自己擦
C语言内存处理

Rust之ownership

一些语言中(如JAVA)具有垃圾回收机制,在程序运行时不断地寻找不再使用的内存;在另一些语言(如C)中,程序员必须亲自分配和释放内存。Rust 则选择了第三种方式:通过ownership系统管理内存,编译器在编译时会根据一系列的规则进行检查。在运行时,ownership(所有权)系统的任何功能都不会减慢程序。

什么是ownership?有什么特征?(所有权规则)
  1. Rust 中的每一个值都有一个被称为其所有者(owner)的变量
{                      
    let s = "hello"; // 这里 s 是 hello 这个值的所有者
}       
  1. 值有且只有一个所有者
fn main() {
    let s = String::from("hello");
    let a = s;
    println!("{}", s);
    println!("{}", a);
}

编译结果:

$ rustc only_one_owner.rs
error[E0382]: use of moved value: `s`
 --> only_one_owner.rs:4:20
  |
3 |     let a = s;
  |         - value moved here
4 |     println!("{}", s);
  |                    ^ value used here after move
  |
  = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

这里清楚的看到,这里编译不通过,因为当我们let a = s的时候,其实String::from("hello")的所有权转移到了变量a上,所以打印s是一个不能成功的操作。

修复后的代码以及输出:

fn main() {
    let s = String::from("hello");
    let a = s;
    println!("{}", a);
}

$ rustc only_one_owner.rs
$ ./only_one_owner
hello
  1. 当所有者(变量)离开作用域,这个值将被丢弃
    很显然,这里就是回收的触发点

更多问题:

  1. 为什么使用let s = String::from("hello")不使用let s = "hello"

String的赋值
一个是引用,一个是值,值的重新绑定是会直接拷贝的,引用的赋值只是拷贝了指针,长度,容量(如上图)

  1. 为什么要有只能有一个owner的限制呢?
    试想如果一个值的所有者是两个变量,那么根据所有权规则第三条,当变量离开作用域的时候,就会释放两次内存(double free)。是不是想想都很可怕,鬼知道会释放了什么东西。。

  2. 我就要赋值两次,行不行?

// 你说了算,这里就是 深浅拷贝 的问题了,应该都知道哈
let s1 = String::from("hello");
let s2 = s1.clone();
println!("s1 = {}, s2 = {}", s1, s2);
调用函数时ownership的变化

举个?:

fn main() {
	let s = String::from("hello");
	let num = 32;
	to(s, num);
	println!("main num:{}", num);
}

fn to(str: String, number: i32) {
	println!("str={},num={}",str, number);
}

编译运行:

$ ./function_owner
str=hello,num=32
main num:32
## 可以看出,main方法中num依然是可以使用的

修改这个例子:打印出变量s

fn main() {
	...
	println!("main num:{}, str:{}", num, s);
}
...
  
  
// 编译报错:
error[E0382]: use of moved value: `s`
 --> function_owner.rs:5:46
  |
4 |     to(s, num);
  |        - value moved here
5 |         println!("main num:{}, str:{}", num, s);
  |                                              ^ value used here after move
  |
  = note: move occurs because `s` has type `std::string::String`, which does not implement the `Copy` trait

error: aborting due to previous error

本质上,还是上面的问题。

函数返回结果时,ownership的变化

应该已经很清楚了,会把被调用函数的返回值的所有权返回给调用方作用域中的变量

fn main() {
	let s1 = String::from("hello");
	let s2 = from(s1);
	// 此时,s1已经不能操作,因为调用函数的时候,所有权已经转移了
	// s2时可以操作的,from函数的返回值的所有者就是 s2
}

fn from(str: String) {
	str
}
你这不行啊,String一旦传递给函数,就不能用了,多浪费啊

考虑下面的代码:

fn main() {
    let s1 = String::from("hello");
    let s2 = s1.clone(); //这一步是必须的,因为调用length()的时候,会发生所有权的转移,所有导致 s1 不再可用
    let len = length(s1);
    println!("'{}'的长度是{}", s2, len);
}
// 计算一个字符串的长度
fn length(s: String) -> usize {
    s.len()
}

这里为了实现功能,我们额外clone了一份数据,是不是感觉多次一举,很不优雅,繁琐。。。

  • 如何解决传递对象(好像这样叫不太合适。。。)数据,导致所有权的转移?
  1. 记得当初学C的时候,有一个概念,指针的指针
  2. Rust上有一个概念 对象的引用&s1表示 s1的引用,并且这种引用并没有所有权,所有权还在被引用的变量(对象)中。
  3. 函数的参数可以声明成 对象的引用
  4. Show Time => (原谅我使用这俩个符号,最近在写Scala)
fn main() {
    let s1 = String::from("hello");
    let len = length(&s1);// 这里传入的是 s1 的引用
    println!("'{}'的长度是{}", s1, len); // 这里 s1 的所有权仍在
}
// 计算一个字符串的长度
fn length(s: &String) -> usize {
    s.len()
} // s 离开作用域,由于s没有引用值的所有权,所以不会进行内存回收

值,对象,对象引用关系图:
借用

要回收,先分类

马云捡到一个神灯
擦了擦灰后
灯神出现了
灯神:”一个愿望?”
马云:”你说。”
灯神:”…”
最后灯神提出了自己的愿望:
“把我扔了吧。” 
马云决定帮它实现这个愿望:
“你是什么垃圾?”


小时候:“妈妈我是从哪里来的?”“你是从垃圾桶里捡来的。”
长大后:“妈妈我是从哪里来的?”“你是从湿垃圾桶里捡来的。”


垃圾分类将至,我从今日开始戒外卖,每天堂食,我将不喝咖啡,不喝奶茶,不食甜品,不吃零食,不买水果,不用护肤品。我是生活中的懒货,懒货中的佼佼者。

参考引用

Rust编程语言
阿里妹妹推的JVM GC文章
C语言内存处理

我的个人博客,有空来坐坐

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值