Rust 在函数内部和返回结构后,结构的内存地址如何相同?

Rust 在函数内部和返回结构后,结构的内存地址如何相同?,rust,Rust,短语“当作用域退出时,值会自动从堆栈中弹出”重复了很多次,但我在这里提供的示例反驳了这一说法: fn main() { let foo = foobar(); println!("The address in main {:p}", &foo); } fn foobar() -> Employee { let emp = Employee { company: String::from("xyz"),

短语“当作用域退出时,值会自动从堆栈中弹出”重复了很多次,但我在这里提供的示例反驳了这一说法:

fn main() {
    let foo = foobar();
    println!("The address in main {:p}", &foo);
}

fn foobar() -> Employee {
    let emp = Employee {
        company: String::from("xyz"),
        name: String::from("somename"),
        age: 50,
    };
    println!("The address inside func {:p}", &emp);
    emp
}

#[derive(Debug)]
struct Employee {
    name: String,
    company: String,
    age: u32,
}
输出为:

函数0x7fffc34011e8中的地址
主目录0x7fffc34011e8中的地址
这是有道理的。当我使用
Box
创建结构时,地址与我预期的不同

  • 如果函数将返回值的所有权(移动)返回给调用方,那么在函数执行后,与该函数对应的内存会弹出,这是不安全的,那么即使在函数退出后,如何访问函数内部创建的结构
  • 返回数组时也会发生同样的情况。这些元素存储在内存中的什么位置,是在堆栈中还是在堆中
  • 编译器会在编译时进行转义分析,并像Go一样将值移动到堆中吗

  • 我确信
    Employee
    不会实现
    Copy
    特性。

    在许多语言中,变量只是一种方便的方法 人类需要命名一些值。 即使从逻辑的角度来看,我们也可以假设有一个 每个特定变量的特定存储,我们可以 这是在复制,移动。。。这并不意味着这些副本 并且实际发生移动(尤其是因为优化器)。 此外,在阅读各种关于生锈的文献时,我们经常会发现 术语绑定而不是变量;这强化了这一观点 我们只是引用某个地方存在的值。 这与编写
    let a=something()完全相同然后
    让b=a,,
    再次
    让c=b。。。我们只是改变了对这个名字的想法
    但实际上没有移动任何数据

    在调试方面,生成的代码通常是 通过为每个变量提供自己的存储来实现次优 以便检查内存中的这些变量。 这可能会误导优化代码的真实性质

    回到您的示例,您发现Rust决定执行 一种返回值优化(当今通用C++术语) 因为它知道临时值必须出现在调用中 上下文提供结果,此结果来自本地 函数中的变量。 因此,与其创建两个不同的存储并从 一个接一个地,最好使用相同的存储:本地存储 变量存储在函数外部(结果是 预期的)。 从逻辑的角度来看,它没有改变任何东西,只是改变了它 它的效率要高得多。 当代码内联开始发挥作用时,没有人能够预测在哪里 我们的变量/值/绑定实际上是存储的


    下面的一些评论指出,此返回值优化 可以指望,因为它发生在铁锈ABI。
    (我还不知道,还是个初学者;^)

    另见;重复多次-引用需要从抽象机器的堆栈中“弹出”和在实际硬件上实际执行时复制到堆栈中的新位置是两件不同的事情。您不能通过运行代码来证明或反驳抽象机器的任何行为。没有理由假设值的地址在传入函数或从函数返回时会发生更改,Rust和C等语言不是低级语言。这意味着,当优化器在函数中找到返回值时,它会在堆栈上创建那些即使函数退出也不会破坏的值,并指向该内存,对吗?@chellathurai
    Employee
    s空间分配在
    main
    s堆栈框架中,不是
    foobar
    s.@chellathurai是的,如果你知道C,这就像提供一个带有指针参数的函数,以便将结果存储在调用上下文中(即使没有任何东西可以保证这确实发生)。你读过Shepmaster的链接吗@prog fh可能没有太多的源,因为Rust ABI不稳定,但是它的概念与中的相同:“如果[…标准…]调用者将地址作为隐式参数传递。然后被调用者将返回值构造到此地址中。”