首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在同一范围内的变量阴影在锈蚀?

在同一范围内的变量阴影在锈蚀?
EN

Stack Overflow用户
提问于 2018-04-22 03:30:48
回答 3查看 1.4K关注 0票数 6
代码语言:javascript
复制
fn main() {
    let x = 5;
    println!("{}", x);

    let x = 3.14;
    println!("{}", x);

    let x = "Hello";
    println!("{}", x);
}
  1. 以前的值发生了什么变化?我的理解是,它们没有被摧毁。
  2. 是否有办法仍然访问这些值?
  3. 如果他们还在消耗内存空间,是否有可能释放这个空间呢?
EN

回答 3

Stack Overflow用户

发布于 2018-04-22 04:47:24

  1. 以前的值发生了什么变化?

没什么。

  1. 是否有办法仍然访问这些值?

不是的。

  1. 如果他们还在消耗内存空间,是否有可能释放这个空间呢?

不是的。

现在,从代码的角度来看,上述所有内容都应该是正确的。从优化者的角度来看,它们不一定是正确的。例如,优化器可能会注意到第一个和第二个x的使用没有重叠,所以它可以为第二个x重用第一个x的堆栈存储。

也可能不会。据我所知,语言本身对这个问题没有意见。

唯一能保证局部变量释放它的堆栈存储的方法是从它定义的函数返回。

..。好吧,直到你考虑了内衬,这也可能使这不是真的。

短版本:不要担心它,除非您占用了太多的堆栈空间,从而导致了实际的、可测量的问题。

票数 5
EN

Stack Overflow用户

发布于 2018-04-22 04:54:43

可以在隐藏变量之前将该值移出,但最终不能从隐藏变量访问该值。

回答Q1:的决定取决于编译器和数据类型和大小以及OS和系统内存负载(通常基于堆栈的数据类型停留在main的末尾,而基于堆的数据类型如果需要的话可能需要减少)。

回答Q2:跟踪后:No,在隐藏之前: Yes (Value),运行这段代码

回答Q3:在阴影之后:没有,在隐藏之前:见:处置价值。和生锈手动内存管理

可变范围和阴影:

优势:

  1. 由于无法从外部范围访问数据,因此数据完整性得以保持。
  2. 当“我们需要更多的字母”时,这是限制变量范围的好方法。而且,当您需要更多的局部变量或作用域时,这也很好。

一种在隐藏之前仍然访问这些的方法(注意:移动迫使闭包获得‘x’的所有权):

代码语言:javascript
复制
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();
    }
}

产出:

代码语言:javascript
复制
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不相同,但是:

代码语言:javascript
复制
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();
    }
}

产出:

代码语言:javascript
复制
0x8bf934
0x8bf9b8
0x8bfa40
Thread 1: 0x4a3faec
Thread 2: 0x4c3fae8
Thread 3: 0x4e3fa70
票数 3
EN

Stack Overflow用户

发布于 2018-04-22 13:05:07

据我所知,只有一件事需要记住:当值被分配时。

来自

请注意,隐藏名称不会改变或破坏它绑定到的值,并且该值将继续存在,直到它超出范围,即使它不再以任何方式访问。

之前的值在隐藏后不会更容易访问,并且它将在作用域结束时被销毁,而不是当变量被隐藏时。

如果堆栈上有值,就没什么好担心的:堆栈内存管理完全掌握在处理器手中。

相反,如果该值是堆分配的,则可以将阴影视为临时内存泄漏,该泄漏将在作用域结束时释放。

如果这可能是一个问题,我们可以在隐藏之前使用drop()显式地释放内存:

代码语言:javascript
复制
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");

}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/49962229

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档