rust - 当 Rust 中一个值覆盖另一个值时,堆栈上会发生什么?

标签 rust borrow-checker borrow

<分区>

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

预计以下是错误,但不是:

for line in reader.lines() {
    let line = line.expect("Could not read line.");

对于完整的上下文,我有 entire code in a gist .这是我修复问题后的代码,相关行是 37 和 38。但是它需要提供一个文本文件作为参数。


我预计会出现错误,因为 line 在堆栈上(至少指针在堆栈上)。它仍然可以毫无怨言地销毁和替换是对的吗?

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

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

let line: f64 = 3.42;

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

最佳答案

只要用 let 声明一个变量,它就是一个全新的变量,与它之前的任何变量都不同。即使已经存在同名变量,原始变量也是shadowed而新变量在范围内。如果一个变量被隐藏,它通常是不可访问的。

在新变量超出范围后旧变量仍在范围内的情况下,或者如果旧变量具有 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.
}

(playground)

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

代码

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

compiles to

example::add_three:
        lea     eax, [rdi + rsi]
        add     eax, edx
        ret

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

  1. 将 x 和 y 相加并将结果放入一个变量中(称之为 w)。
  2. 将 z 添加到 w 并用结果覆盖 w。
  3. 返回 w.

所以(除了输入参数),只使用了一个变量,即使我们使用了两次 let x = ... 。中间结果 let x = x + y; 被覆盖。

关于rust - 当 Rust 中一个值覆盖另一个值时,堆栈上会发生什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56370397/

相关文章:

file - Rust 读取文件

rust - 如何使从对象到其孙子的生命周期约束 "pass through"?

rust - 独立于方法返回 RWLockReadGuard

rust - 与可变借用相关的不可变借用导致 "cannot borrow ` *self` 一次多次可变”

rust - 不能将 `hsets` 借为可变,因为它也被借为不可变

使用rust 错误 : borrow occurs after drop a mutable borrow

struct - 如何在强制使用 "new"构造函数的同时使结构的所有字段公开可读

string - 如何创建静态 C 字符串?

rust - 如何在成员方法闭包中使用struct self

rust - 借用中间变量可绕过的错误