为什么Rust中的“移动”实际上没有移动?

时间:2018-11-25 08:31:02

标签: rust

在下面的示例中:

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);
}

我发现在传递到函数foo前后,f的地址是不同的。为什么Rust到处都会复制这么大的结构,却没有真正移动它(或实现此优化)?

我了解堆栈存储器的工作原理。但是利用Rust中所有权提供的信息,我认为可以避免复制。编译器不必要地复制了两次数组。这可以对Rust编译器进行优化吗?

1 个答案:

答案 0 :(得分:4)

举动是一种记忆,其后将源视为不存在。

您的大数组在堆栈中。这就是Rust的内存模型的工作方式:局部变量在堆栈中。由于函数返回时foo的堆栈空间将消失,因此编译器除了将内存复制到main的堆栈空间之外,无能为力。

在某些情况下,编译器可以重新安排事情,以便消除移动(将源和目标合并为一件事),但这是不能依靠的优化,尤其是对于大事情。

如果您不想复制巨大的数组,请自己通过Box<[u64]>或直接使用Vec<u64>在堆上分配它。

相关问题