fn main() {
let x = 5;
println!("{}", x);
let x = 3.14;
println!("{}", x);
let x = "Hello";
println!("{}", x);
}
以前的值会怎样?我的理解是它们没有被摧毁。
有没有办法仍然访问这些值?
如果他们仍在消耗内存空间,是否可以释放该空间?
- 以前的值会发生什么?
什么都没有。
- 有没有办法仍然访问这些值?
no。
- 如果他们仍在消耗内存空间,是否可以释放该空间?
no。
现在,从代码的角度来看,以上所有内容都应该是正确的。从优化器的角度来看,它们不一定是 true。例如,优化器可能会注意到,第一和第二x
的使用不会重叠,因此它可以重新使用第二个x
的第一个x
的堆栈存储。
否则可能不会。据我所知,语言本身对这个主题没有意见。
我意识到的唯一方法是,您可以保证 local变量将绝对释放其堆栈存储是从定义的函数中返回的。<<<<<<<<<<<<<<<<<<<</p>
...好吧,直到您考虑 inling ,这也可能使它不正确。
简短版本:不用担心,除非您使用的是太多的堆栈空间,从而导致了实际的,可衡量的问题。
可以在变量被遮蔽之前将值移出,但是 最终,该值无法从阴影变量访问。
回答Q1:决策取决于编译器以及数据类型,大小以及OS和系统内存加载(通常基于堆栈的数据类型保持到main
的末尾,以及基于HEAP的数据带有大型内存足迹的类型可能需要在需要时掉落(。
回答Q2:阴影后:否,在阴影之前:是( values (,运行此代码。
回答Q3:阴影后:否,在阴影之前:请参阅:处置值。和生锈手动记忆管理
可变范围和阴影:
优点:
1.由于无法从外部范围访问数据,因此可以保留数据完整性。
2.当"我们需要更多字母"时,这是限制变量范围的好方法。当您需要更多本地变量或范围时,这也很好。
在阴影之前仍然访问这些值的一种方法(注意:移动强迫关闭以获取'x'的所有权(:
use std::{thread, time};
fn main() {
let mut v = vec![];
let d = time::Duration::from_millis(100);
let x = 5;
println!("{}", x);
v.push(thread::spawn(move || {
for _ in 1..10 {
thread::sleep(d);
println!("Thread 1: {}", x);
}
}));
let x = 3.14;
println!("{}", x);
v.push(thread::spawn(move || {
for _ in 1..10 {
thread::sleep(d);
println!("Thread 2: {}", x);
}
}));
let x = "Hello";
println!("{}", x);
v.push(thread::spawn(move || {
for _ in 1..10 {
thread::sleep(d);
println!("Thread 3: {}", x);
}
}));
for child in v {
let _ = child.join();
}
}
输出:
5
3.14
Hello
Thread 1: 5
Thread 3: Hello
Thread 2: 3.14
Thread 2: 3.14
Thread 3: Hello
Thread 1: 5
Thread 1: 5
Thread 3: Hello
Thread 2: 3.14
Thread 2: 3.14
Thread 3: Hello
Thread 1: 5
Thread 2: 3.14
Thread 3: Hello
Thread 1: 5
Thread 2: 3.14
Thread 1: 5
Thread 3: Hello
Thread 2: 3.14
Thread 1: 5
Thread 3: Hello
Thread 3: Hello
Thread 2: 3.14
Thread 1: 5
Thread 1: 5
Thread 2: 3.14
Thread 3: Hello
注意:move
强制闭合'X'所有权,因此本地x
的地址与线程x
不同,但是 value is:
use std::thread;
fn main() {
let mut v = vec![];
let x = 5;
println!("{:p}", &x);
v.push(thread::spawn(move || {
println!("Thread 1: {:p}", &x);
}));
let x = 3.14;
println!("{:p}", &x);
v.push(thread::spawn(move || {
println!("Thread 2: {:p}", &x);
}));
let x = "Hello";
println!("{:p}", &x);
v.push(thread::spawn(move || {
println!("Thread 3: {:p}", &x);
}));
for child in v {
let _ = child.join();
}
}
输出:
0x8bf934
0x8bf9b8
0x8bfa40
Thread 1: 0x4a3faec
Thread 2: 0x4c3fae8
Thread 3: 0x4e3fa70
据我所知,只有一件事要牢记阴影:当值分配时。
从书中:
请注意,阴影名称不会更改或破坏其所绑定的值,并且该值将继续存在,直到其范围超出范围,即使它不再可以通过任何方式访问
阴影后,以前的值不太容易访问,它将是在示波器的末端被摧毁,而不是在变量被阴影时被摧毁。
如果值在堆栈上,则没有什么可担心的:堆栈内存管理完全在处理器的手中。
相反,如果该值分配了堆,则可以将阴影视为临时内存泄漏,将在示波器的末端释放。
如果这可能是一个问题,我们可以在阴影前用drop()
明确释放内存:
struct Foo {
_v: Vec<i32>
}
impl Drop for Foo {
fn drop(&mut self) {
println!("dropping foo");
}
}
fn main() {
println!("start");
let x = Foo {_v: vec![1,2,3]};
drop(x);
let x = 100;
println!("end");
}