Rust 当一个值与另一个值成反差时,堆栈上会发生什么情况?

Rust 当一个值与另一个值成反差时,堆栈上会发生什么情况?,rust,borrow-checker,borrow,Rust,Borrow Checker,Borrow,我正在读书。在第一章末尾有一个练习,其中提供了示例代码,任务是修复它,通过使用通常非常有用的编译器错误消息进行迭代 我原以为以下是一个错误,但它不是: 读取器中的行的。行(){ let line=line.expect(“无法读取行”); 对于完整的上下文,我有。这是我修复后的代码,相关的行是37和38。但是它需要输入一个文本文件作为参数 我以为会发生错误,因为行在堆栈上(至少指针在堆栈上)。它仍然可以被销毁和替换,而不必抱怨,这对吗 关于内存管理和堆栈,后台会发生什么?我假定line实际上

我正在读书。在第一章末尾有一个练习,其中提供了示例代码,任务是修复它,通过使用通常非常有用的编译器错误消息进行迭代

我原以为以下是一个错误,但它不是:

读取器中的行的
。行(){
let line=line.expect(“无法读取行”);
对于完整的上下文,我有。这是我修复后的代码,相关的行是37和38。但是它需要输入一个文本文件作为参数


我以为会发生错误,因为
在堆栈上(至少指针在堆栈上)。它仍然可以被销毁和替换,而不必抱怨,这对吗

关于内存管理和堆栈,后台会发生什么?我假定
line
实际上是对字符串的引用(a
&str
类型)因此,这很好,因为在任何一种情况下,指针本身(堆栈上的对象)只是一个
usize
,因此这两个
对象在堆栈上的大小相同

我可以用不同尺寸的吗?第二行可以说:

let行:f64=3.42;

在这种情况下,对象本身在堆栈上,并且它可能大于
usize

每当使用
let
声明变量时,它都是一个全新的变量,与之前的任何变量都是分开的。即使具有相同名称的变量已经存在,原始变量仍然存在,而新变量在作用域中。I如果一个变量被隐藏,它通常是不可访问的

在新变量超出范围后旧变量仍在范围内的情况下,或者旧变量具有
Drop
实现时,可以访问旧变量的值

我们可以在下面的例子中看到这一点

#[derive(Debug)]
struct DroppedU32(u32);

impl Drop for DroppedU32 {
    fn drop(&mut self) {
        eprintln!("Dropping u32: {}", self.0);
    }
}

fn main() {
    let x = 5;
    dbg!(&x); // the original value
    {
        let x = 7;
        dbg!(&x); // the new value
    }
    dbg!(&x); // the original value again

    let y = DroppedU32(5);
    dbg!(&y); // the original value
    let y = DroppedU32(7);
    dbg!(&y); // the new value

    // down here, when the variables are dropped in
    // reverse order of declaration,
    // the original value is accessed again in the `Drop` impl.
}

这并不是说原始变量保证仍然存在。编译器优化可能会导致原始变量被覆盖,特别是当原始变量不再被访问时

代码

pub fn add_three(x: u32, y: u32, z: u32) -> u32 {
    let x = x + y;
    let x = x + z;
    x
}

如果你和我一样,对汇编代码不太熟悉,基本上

  • 将x和y相加,并将结果放入一个变量(称为w)
  • 将z添加到w并用结果覆盖w
  • 返回w

  • So(除输入参数外),只使用了一个变量,尽管我们使用了两次
    let x=…
    。中间结果
    let x=x+y;
    被覆盖。

    谢谢你,@SCappella!这回答了我的大部分困惑,但现在我有了另一个。我理解逻辑上发生的事情,但不理解内存分配和Rust中发生的事情0-成本抽象。如果我是影子,但在相同的范围内,就像你的第一个例子(
    let x=5;
    let x=7
    ),因为它是同一个作用域,所以不再存在
    x=5
    的作用域。所以,在这种情况下,让x:i32=5
    发生了什么事?
    让x:u64=7
    ?我的问题是:我在堆栈上有一个32位的项,它现在是同一堆栈位置上的64位项,对吗?我怎么做呢?@MikeWilliamson他们不占用相同的位置堆栈位置。原始变量被设置为不可访问,但它在内存中仍然保持不变。我将添加一个示例来说明这一点。@MikeWilliamson考虑它的最佳方式是将内部
    x
    视为一个完全不同的变量,具有不同的名称。想象一下编译器甚至在内部重命名它(或表现得好像有)。很明显,这两个函数并不共享相同的堆栈位置,它们的类型也不存在任何问题。太好了,谢谢@SCappella!顺便说一句,你如何获得字节码,或者它编译成什么?在Python中,我使用了
    dis
    库。Rust中有类似的东西吗?如果有,这是如何管理的,因为Rust编译到特定的体系结构/操作系统(同一个程序会在不同的平台上创建不同的字节码吗?或者字节码只是一个中介,就像在JVM或Python中一样?)@MikeWilliamson如果您想使用Cargo获取程序集,请参阅。如果您对在线工具没有异议,请查看。还可以选择发出程序集和Rust使用的其他中间表示形式。对于您的其他问题,请尝试提出新问题,我相信您会得到一个很好的答案。@Stargateur我不认为这是完全重复的,因为我潜在的问题不是为什么这是好的,而是如何这是好的?如何在引擎盖下的堆栈中发生事情以使这成为可能?是否有两个不同的对象,一个是旧的
    ,另一个是新的
    ,即使旧的不再可访问?还是旧的uly覆盖(如果在同一范围内)?如果是,对于不同大小的类型,如何实现?
    example::add_three:
            lea     eax, [rdi + rsi]
            add     eax, edx
            ret