Ale*_*una 14 memory-management rust
我在Rust书中看到,您可以使用相同的名称定义两个不同的变量:
let hello = "Hello";
let hello = "Goodbye";
println!("My variable hello contains: {}", hello);
Run Code Online (Sandbox Code Playgroud)
打印出:
My variable hello contains: Goodbye
Run Code Online (Sandbox Code Playgroud)
第一次打招呼怎么了?它被释放了吗?我怎么能访问它?
我知道将两个变量命名为相同会很糟糕,但如果这种情况偶然发生,因为我将其声明为100行以下,这可能是一个真正的痛苦.
She*_*ter 13
Rust是否释放了被覆盖变量的记忆?
是的,否则它将是一个内存泄漏,这将是一个非常可怕的设计决定.
第一个问候会发生什么
它被遮蔽了.
变量引用的数据没有任何"特殊"发生,除了您无法再访问它的事实.当变量超出范围时,它仍然被丢弃.
这是在删除每个变量时打印出来的代码:
struct Noisy;
impl Drop for Noisy {
fn drop(&mut self) {
println!("Dropped")
}
}
fn main() {
println!("0");
let thing = Noisy;
println!("1");
let thing = Noisy;
println!("2");
}
Run Code Online (Sandbox Code Playgroud)
0
1
2
Dropped
Dropped
Run Code Online (Sandbox Code Playgroud)
我知道将两个变量命名为相同是不好的
它不是"坏",这是一个设计决定.我会说像这样使用阴影是一个坏主意:
let x = "Anna";
println!("User's name is {}", x);
let x = 42;
println!("The tax rate is {}", x);
Run Code Online (Sandbox Code Playgroud)
像这样使用阴影对我来说是合理的:
let name = String::from(" Vivian ");
let name = name.trim();
println!("User's name is {}", x);
Run Code Online (Sandbox Code Playgroud)
也可以看看:
但如果这种情况偶然发生,因为我宣布它下面100行,这可能是一个真正的痛苦.
没有那么大的功能,你"意外"做某事.这适用于任何编程语言.
有没有办法手动清理内存?
你可以打电话drop:
println!("0");
let thing = Noisy;
drop(thing);
println!("1");
let thing = Noisy;
println!("2");
Run Code Online (Sandbox Code Playgroud)
0
Dropped
1
2
Dropped
Run Code Online (Sandbox Code Playgroud)
但是,正如oli_obk - ker指出的那样,变量占用的堆栈内存在函数退出之前不会释放,只有变量占用的资源才会释放.
所有关于drop的讨论都需要展示它(非常复杂)的实现:
fn drop<T>(_: T) {}
Run Code Online (Sandbox Code Playgroud)
如果我在其他函数之外的全局范围内声明变量怎么办?
如果您甚至可以创建全局变量,那么它们永远不会被释放.
在降序时,阴影和覆盖变量之间存在差异.
所有局部变量在超出范围时通常会以与声明相反的顺序被删除(请参阅Rust编程语言的章节Drop).这包括阴影变量.通过将值包装在一个简单的包装器结构中来检查这一点很容易,该结构在它(包装器)被删除时(在删除值本身之前)打印一些东西:
use std::fmt::Debug;
struct NoisyDrop<T: Debug>(T);
impl<T: Debug> Drop for NoisyDrop<T> {
fn drop(&mut self) {
println!("dropping {:?}", self.0);
}
}
fn main() {
let hello = NoisyDrop("Hello");
let hello = NoisyDrop("Goodbye");
println!("My variable hello contains: {}", hello.0);
}
Run Code Online (Sandbox Code Playgroud)
打印以下(游乐场):
My variable hello contains: Goodbye
dropping "Goodbye"
dropping "Hello"
Run Code Online (Sandbox Code Playgroud)
那是因为let范围中的新绑定不会覆盖以前的绑定,所以就像你写的一样
let hello1 = NoisyDrop("Hello");
let hello2 = NoisyDrop("Goodbye");
println!("My variable hello contains: {}", hello2.0);
Run Code Online (Sandbox Code Playgroud)
请注意,此行为不同于以下表面非常相似的代码(playground):
fn main() {
let mut hello = NoisyDrop("Hello");
hello = NoisyDrop("Goodbye");
println!("My variable hello contains: {}", hello.0);
}
Run Code Online (Sandbox Code Playgroud)
这不仅会以相反的顺序丢弃它们,而是在打印消息之前删除第一个值!这是因为当你分配给一个变量(而不是用一个新的阴影吧),原来的值被丢弃第一,之前的新值中移动.
我首先说当局部变量超出范围时"正常"掉线.因为您可以将值移入和移出变量,所以有时候直到运行时才能分析确定何时需要删除变量.在这种情况下,编译器实际上会插入代码来跟踪"活跃度"并在必要时删除这些值,因此您不会通过覆盖值而意外地导致泄漏.(但是,仍然可以通过调用mem::forget或通过创建Rc具有内部可变性的循环来安全地泄漏内存.)
| 归档时间: |
|
| 查看次数: |
1216 次 |
| 最近记录: |