Why does “move” in Rust not actually move?

醉酒当歌 提交于 2020-05-25 04:32:06

问题


In the below example:

struct Foo {
    a: [u64; 100000],
}

fn foo(mut f: Foo) -> Foo {
    f.a[0] = 99999;
    f.a[1] = 99999;
    println!("{:?}", &mut f as *mut Foo);

    for i in 0..f.a[0] {
        f.a[i as usize] = 21444;
    }

    return f;
}
fn main(){
    let mut f = Foo {
        a:[0;100000]
    };

    println!("{:?}", &mut f as *mut Foo);
    f = foo(f);
    println!("{:?}", &mut f as *mut Foo);
}

I find that before and after passing into the function foo, the address of f is different. Why does Rust copy such a big struct everywhere but not actually move it (or achieve this optimization)?

I understand how stack memory works. But with the information provided by ownership in Rust, I think the copy can be avoided. The compiler unnecessarily copies the array twice. Can this be an optimization for the Rust compiler?


回答1:


A move is a memcpy followed by treating the source as non-existent.

Your big array is on the stack. That's just the way Rust's memory model works: local variables are on the stack. Since the stack space of foo is going away when the function returns, there's nothing else the compiler can do except copy the memory to main's stack space.

In some cases, the compiler can rearrange things so that the move can be elided (source and destination are merged into one thing), but this is an optimization that cannot be relied on, especially for big things.

If you don't want to copy the huge array around, allocate it on the heap yourself, either via a Box<[u64]>, or simply by using Vec<u64>.



来源:https://stackoverflow.com/questions/53465843/why-does-move-in-rust-not-actually-move

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!