fn main() {
let s: String = "Hello, World!".into();
let t = s;
println!("{}", s);
}
产量:
<anon>:4:24: 4:25 error: use of moved value: `s` [E0382]
<anon>:4 println!("{}", s);
<anon>:3:13: 3:14 note: `s` moved here because it has type `collections::string::String`, which is moved by default
<anon>:3 let t = s;
^
4条答案
按热度按时间w3nuxt5m1#
垃圾收集通常是周期性地或者按需使用的,比如当堆接近满或者超过某个阈值时,它会寻找未使用的变量并释放它们的内存,这取决于algorithm。
Rust会知道变量何时超出作用域或其生命周期何时在编译时结束,从而插入相应的LLVM/汇编指令来释放内存。
Rust还允许某种垃圾收集,比如atomic reference counting。
bvk5enib2#
在程序中管理资源(包括内存)的基本思想是,无论采用何种策略,绑定到不可达"对象"的资源都可以回收。除了内存,这些资源还可以是互斥锁、文件句柄、套接字、数据库连接......
具有垃圾收集器的语言定期扫描内存(一种方式或另一种方式)以查找未使用的对象,释放与它们相关联的资源,并最终释放那些对象使用的内存。
Rust没有GC,它是如何管理的?
Rust拥有所有权。使用仿射类型系统,它跟踪哪个变量仍然持有一个对象,当这样的变量超出作用域时,调用它的析构函数。你可以很容易地看到仿射类型系统的效果:
产量:
这完美地说明了在任何时间点,在语言级别,所有权都被跟踪。
此所有权以递归方式工作:如果你有一个
Vec<String>
(即字符串的动态数组),那么每个String
都被Vec
所拥有,而Vec
本身又被一个变量或另一个对象所拥有,等等。因此,当一个变量超出作用域时,它会递归地释放它所拥有的所有资源,甚至间接地释放。1.释放与每个
String
关联的内存缓冲区1.释放与
Vec
本身关联的内存缓冲区因此,多亏了所有权跟踪,所有程序对象的生命周期都严格地绑定到一个(或几个)函数变量,这些变量最终将超出作用域(当它们所属的块结束时)。
Rc
或Arc
)可能会形成引用循环,从而导致内存泄漏,在这种情况下,绑定到循环的资源可能永远不会释放。*iqih9akk3#
对于一种必须手动管理内存的语言,堆栈和堆之间的区别变得至关重要。每次调用函数时,都会在堆栈上为该函数作用域中包含的所有变量分配足够的空间。当函数返回时,与该函数关联的堆栈帧会从堆栈中“弹出”,内存将被释放以供将来使用。
从实际的Angular 来看,这种无意的内存清理被用作自动内存存储的一种方法,它将在函数作用域结束时被清除。
更多信息请访问:https://doc.rust-lang.org/book/the-stack-and-the-heap.html
qlfbtfca4#
有些语言有引用计数,有些有垃圾收集器。Rust避免了两者,相反,如果你想在任何时间点拥有一个内存位置,它只允许单个变量名或别名。你可以将所有权从一个变量名移动到另一个变量名,但是你不能让两个变量名指向同一个内存地址(除了共享所有权之外。Rust提供引用计数指针类型Rc和Arc。双向链表)。
Rust使用了一种相对独特的内存管理方法,它融入了内存“所有权”的思想。基本上,Rust会跟踪谁可以读写内存。它知道程序何时在使用内存,一旦不再需要就会立即释放内存。它在编译时强制执行内存规则,这使得运行时内存错误几乎不可能发生。2你不需要手动跟踪内存。3编译器会处理它。
Discord最近在它的一个服务中从Go切换到了Rust,仅仅是因为垃圾收集器导致了延迟。他们很好地解释了为什么他们这样做,你会了解到更多关于垃圾收集器和Rust内存系统的信息:
为什么不和谐要从“去 rust ”转变为“ rust ”#:~:text=不和谐关注的是一个产品,并且您已经阅读了%20封邮件。