考虑片段

struct Foo {
    dummy: [u8; 65536],
}

fn bar(foo: Foo) {
    println!("{:p}", &foo)
}

fn main() {
    let o = Foo { dummy: [42u8; 65536] };
    println!("{:p}", &o);
    bar(o);
}

典型的result个项目是

0x7fffc1239890
0x7fffc1229890

地址不同的地方.

显然,正如编译器的move实现所预期的那样,大数组dummy已被复制.不幸的是,这可能会对性能产生不小的影响,因为dummy是一个非常大的array.这种影响会迫使人们 Select 通过引用传递参数,即使函数实际上在概念上"消耗"了参数.

因为Foo不派生Copy,所以对象o被移动.由于 rust 迹禁止访问移动的对象,是什么阻止bar"重用"原始对象o,迫使编译器生成可能昂贵的位拷贝?有没有一个根本性的困难,或者有一天我们会看到编译器优化掉这个逐位拷贝?

推荐答案

考虑到在 rust (不像C或C++)中,一个值的地址不被认为是重要的,在language个方面没有任何东西阻止拷贝的删除.

然而,如今rustc并没有优化任何东西:所有的优化都委托给LLVM,而且似乎您在这里遇到了LLVM优化器的一个限制(不清楚这个限制是由于LLVM接近C的语义,还是仅仅是一个遗漏).

因此,有两种改进代码生成的方法:

  • 教LLVM执行此优化(如果可能)
  • 教rustc执行此优化(rustc现在有了MIR,优化通行证就来了)

但现在,您可能只想避免在堆栈上分配如此大的对象,例如,您可以将其设置为Box.

Rust相关问答推荐

是否有一种可靠的方法可以将Arc弦乐转换/转换为Arc Vec u8>>

使用DeliverProcess W或ShellExecuteExW复制Windows Run行为?

为什么这些From A和From B植入会导致重复的实现错误?

if let声明中临时对象的生存期

为什么幻影数据不能自动推断?

trait声明中的生命周期参数

如何在AVX2中对齐/旋转256位向量?

为什么 tokio 在以奇怪的方式调用时只运行 n 个任务中的 n-1 个?

带引脚和不带引脚的比较功能

Rust 中的复合 `HashSet` 操作或如何在 Rust 中获得 `HashSet` 的显式差异/并集

Rust 重写函数参数

为什么我可以使用 &mut (**ref) 创建两个实时 &mut 到同一个变量?

Rust:为什么 Pin 必须持有指针?

&self 参数在 trait 的功能中是必需的吗?

如何将 Rust 中的树状 struct 展平为 Vec<&mut ...>?

返回引用字符串的future

为什么拥有 i32 所有权的函数需要它是可变的?

仅当满足外部条件时如何添加到 actix web 的路由

Abortable:悬而未决的期货?

在 Rust 中退出进程