首页 文章

返回位置的值是否总是在父堆栈框架或接收框中分配?

提问于
浏览
6

我试图了解从方法返回时结构的行为 . “Rust Book”的nightlies部分有一节说如果你使用了语法......

let x = box i_return_a_struct();

..没有副本,因此不需要返回指针 . 但是当我开始玩它时,似乎不需要 box ,除非您需要在堆上存在该值 .

#[derive(Debug)]
struct Dummy {
    data: i64,
}

impl Drop for Dummy {
    fn drop(&mut self) {
        println!("{:?} is going out of scope", self as *const Dummy);
    }
}

fn make_dummy(i: i64) -> Dummy {
    Dummy { data: i }
}

fn main() {
    {
        let i = 15i32;
        println!("{:?} is a variable on the stack frame", &i as *const i32);

        let dummy1 = make_dummy(1);
        println!("{:?} was returned and is being used", &dummy1 as *const Dummy);
        let dummy2 = make_dummy(2);
        println!("{:?} was returned and is being used", &dummy2 as *const Dummy);

        let dummy3 = Box::new(make_dummy(3));
        println!("{:?} box was returned and is being used", &(*dummy3) as *const Dummy);
        let dummy4 = Box::new(make_dummy(4));
        println!("{:?} box was returned and is being used", &(*dummy4) as *const Dummy);
    }
    println!("Leaving main");
}

输出:

0x23fb94 is a variable on the stack frame
0x23faf8 was returned and is being used
0x23fa50 was returned and is being used
0x2825030 box was returned and is being used
0x2825040 box was returned and is being used
0x2825040 is going out of scope
0x2825030 is going out of scope
0x23fa50 is going out of scope
0x23faf8 is going out of scope
Leaving main

返回位置的值/结构是否总是在父堆栈框架或接收框中分配?

编辑:PS - 在文档中是否有任何关于何时复制省略发生的指导?

编辑:除了公认的解决方案之外,以下Q A具有启发性:What are move semantics exactly?为我澄清了许多要点 .

1 回答

  • 2

    也许我不清楚你不理解的是什么 . 我想你明白了,但也许你还不知道:D

    通常,函数的返回值(例如 make_dummy )被压入堆栈 . 现在假设你想要堆上的对象 . 使用新的框语法,如果您希望堆上的对象,编译器可以进行一些优化 .

    现在让我们以书中的例子为例 .

    let y: Box<Dummy> = box make_dummy(some_dummy);
    

    您可能认为在上面的示例中会发生以下情况:

    • make_dummy 的返回值被写入堆栈(正常情况下)

    • 分配一个框以包含 Dummy 对象

    • 堆栈上的 Dummy 值被框对象复制到内存指针中 .

    使用旧的 Box::new 机制,这正是将要发生的事情 . 相反,由于实验框语法,这发生了:

    • 已分配一个框

    • 指向该框的指针以某种方式传递给 make_dummy 函数(带有一些编译器魔法),因此返回值被写入 directly 到盒装内存[没有涉及堆栈的额外副本]

    我希望现在更清楚了 .

相关问题