Memory management 生锈会释放被覆盖变量的内存吗?

Memory management 生锈会释放被覆盖变量的内存吗?,memory-management,rust,Memory Management,Rust,我在Rust书中看到,可以用相同的名称定义两个不同的变量: let hello = "Hello"; let hello = "Goodbye"; println!("My variable hello contains: {}", hello); 这将打印出: 我的变量hello包含:再见 第一次打招呼会发生什么?它被释放了吗?我怎样才能访问它 我知道给两个变量取相同的名字是不好的,但如果这是偶然发生的,因为我在下面100行处声明了它,这可能是一个真正的痛苦。 生锈会释放被覆盖变量的内存

我在Rust书中看到,可以用相同的名称定义两个不同的变量:

let hello = "Hello";
let hello = "Goodbye";

println!("My variable hello contains: {}", hello);
这将打印出:

我的变量hello包含:再见
第一次打招呼会发生什么?它被释放了吗?我怎样才能访问它

我知道给两个变量取相同的名字是不好的,但如果这是偶然发生的,因为我在下面100行处声明了它,这可能是一个真正的痛苦。

生锈会释放被覆盖变量的内存吗

是的,否则将是内存泄漏,这将是一个非常糟糕的设计决策。重新分配变量时将释放内存:

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) {
        eprintln!("Dropped")
    }
}

fn main() {
    eprintln!("0");
    let mut thing = Noisy;
    eprintln!("1");
    thing = Noisy;
    eprintln!("2");
}
0
1.
下降
2.
下降
第一次打招呼会发生什么

是的

变量引用的数据没有任何“特殊”情况,只是您无法再访问它。当变量超出范围时,它仍然会被删除:

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) {
        eprintln!("Dropped")
    }
}

fn main() {
    eprintln!("0");
    let thing = Noisy;
    eprintln!("1");
    let thing = Noisy;
    eprintln!("2");
}
0
1.
2.
下降
下降
另见:

我知道给两个变量取相同的名字是不好的

这不是“坏”,这是一个设计决定。我想说,像这样使用阴影是个坏主意:

let x = "Anna";
println!("User's name is {}", x);
let x = 42;
println!("The tax rate is {}", x);
这样使用阴影对我来说是合理的:

let name = String::from("  Vivian ");
let name = name.trim();
println!("User's name is {}", name);
另见:

但如果这是偶然发生的,因为我宣布它在100行以下,这可能是一个真正的痛苦

不要有太大的函数以至于你“意外”做了一些事情。这适用于任何编程语言

有没有办法手动清理内存

你可以致电:

0
下降
1.
2.
下降
但是,由于变量占用的堆栈内存在函数退出之前不会被释放,只有变量占用的资源才会被释放

所有关于
drop
的讨论都需要显示其(非常复杂)的实现:

fn drop<T>(_: T) {}
fn-drop(u:T){
如果我在其他函数之外的全局范围内声明变量会怎么样

全局变量永远不会被释放,如果您甚至可以创建它们开始的话。

生锈会释放被覆盖变量的内存吗

是的,否则将是内存泄漏,这将是一个非常糟糕的设计决策。重新分配变量时将释放内存:

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) {
        eprintln!("Dropped")
    }
}

fn main() {
    eprintln!("0");
    let mut thing = Noisy;
    eprintln!("1");
    thing = Noisy;
    eprintln!("2");
}
0
1.
下降
2.
下降
第一次打招呼会发生什么

是的

变量引用的数据没有任何“特殊”情况,只是您无法再访问它。当变量超出范围时,它仍然会被删除:

struct Noisy;
impl Drop for Noisy {
    fn drop(&mut self) {
        eprintln!("Dropped")
    }
}

fn main() {
    eprintln!("0");
    let thing = Noisy;
    eprintln!("1");
    let thing = Noisy;
    eprintln!("2");
}
0
1.
2.
下降
下降
另见:

我知道给两个变量取相同的名字是不好的

这不是“坏”,这是一个设计决定。我想说,像这样使用阴影是个坏主意:

let x = "Anna";
println!("User's name is {}", x);
let x = 42;
println!("The tax rate is {}", x);
这样使用阴影对我来说是合理的:

let name = String::from("  Vivian ");
let name = name.trim();
println!("User's name is {}", name);
另见:

但如果这是偶然发生的,因为我宣布它在100行以下,这可能是一个真正的痛苦

不要有太大的函数以至于你“意外”做了一些事情。这适用于任何编程语言

有没有办法手动清理内存

你可以致电:

0
下降
1.
2.
下降
但是,由于变量占用的堆栈内存在函数退出之前不会被释放,只有变量占用的资源才会被释放

所有关于
drop
的讨论都需要显示其(非常复杂)的实现:

fn drop<T>(_: T) {}
fn-drop(u:T){
如果我在其他函数之外的全局范围内声明变量会怎么样


全局变量永远不会被释放,如果你甚至可以创建它们作为开始。

当涉及到删除顺序时,隐藏和重新分配(覆盖)变量是有区别的

所有局部变量通常在超出范围时被删除,顺序与声明相反(请参阅Rust编程语言的)。这包括阴影变量。通过将值包装在一个简单的包装器结构中,可以很容易地检查这一点,该结构在删除该值(包装器)时(就在删除该值之前)打印一些内容:

这是因为作用域中新的
let
绑定不会覆盖以前的绑定,因此就像您编写了

    let hello1 = NoisyDrop("Hello");
    let hello2 = NoisyDrop("Goodbye");

    println!("My variable hello contains: {}", hello2.0);

请注意,此行为与下面的代码()不同,表面上非常相似:

这不仅会以相反的顺序删除它们,还会在打印消息之前删除第一个值!这是因为当你赋值给一个变量(而不是用一个新的变量来隐藏它)时,在新值移入之前,原始值会先被删除

我首先说,局部变量在超出范围时“通常”会被删除。因为您可以将值移入和移出变量,所以有时要等到运行时才能完成确定何时需要删除变量的分析。在这种情况下,编译器实际上会自动关闭,因此您不会因为覆盖某个值而意外导致泄漏。(但是,通过调用
mem::forget
,或者通过创建具有内部可变性的
Rc
-循环,仍然可以安全地泄漏内存。)

另见

当涉及到删除顺序时,隐藏和重新分配(覆盖)变量是有区别的

所有局部变量通常在超出范围时被删除,顺序与声明相反(请参阅Rust编程语言的)。这包括阴影变量。通过将值包装在一个简单的包装器结构中,可以很容易地检查这一点,该结构在删除该值(包装器)时(就在删除该值之前)打印一些内容:

这是因为作用域中新的
let
绑定不会覆盖以前的绑定,因此就像您编写了

    let hello1 = NoisyDrop("Hello");
    let hello2 = NoisyDrop("Goodbye");

    println!("My variable hello contains: {}", hello2.0);

请注意,此行为与下面的代码()不同,表面上非常相似:

这不仅使它们按相反的顺序下降,而且使t下降