如果可能,实现 copy 的类型是否会被移动?

pap*_*arp 4 rust

如果您将一个类型传递给一个不是指针类型的函数并且它实现了 Copy,那么 Rust 是否仅在必要时才复制它?

下面是一些具体的代码:

#[derive(Clone, Copy)]
struct Data([u8; 2]);

#[derive(Clone, Copy)]
struct Buffer(Data);

fn do_something(id: Buffer) {
    println!("{}", id.0.0[0]);
}

fn create_buffer() -> Buffer {
   Buffer(Data([0x01, 0x01]))
}

fn main() {
    let buffer = create_buffer();

    // Since we don't use buffer again in this function, copy trait isn't necessary on Buffer.
    // But, "Buffer" does implement the Copy trait. Will Rust copy it anyway?
    do_something(buffer);
}
Run Code Online (Sandbox Code Playgroud)

如果 rust 不复制它,这种行为是否有规则,还是完全由编译器决定?我可以依靠这个不被复制吗?

如果我要调用 do_something(buffer) 两次怎么办?它是复制两次,还是移动一次并复制一次?这需要复制特征甚至编译,所以我希望至少有 1 个副本。

do_something(buffer);
do_something(buffer);
Run Code Online (Sandbox Code Playgroud)

Mas*_*inn 6

move 和 copy 是唯一的类型系统问题,表示源在使用一次后是否仍然可以使用(由高级代码)[0]。在行话中,它只定义类型是仿射(又名移动,默认)还是正常 ( Copy)

类型检查后,两者都会导致相同的实际操作:内存复制(语义上),然后正常的省略优化对两者的工作方式相同,并且可能会优化掉实际的副本。

所以答案是“是”。在代码生成级别,复制和非复制类型之间确实没有区别,只要它们以相同的方式使用即可。请注意,在这两种情况下,省略优化都可能无法触发。事实上,跟踪器上存在一些问题(有些是关闭的,有些不是),其中“移动省略”无法触发,并且大量的堆栈上非复制类型被复制。

[0] 我相信在 MIR / rustc 本身有有限的 NRVO 和更多计划,但绝大多数工作留给 LLVM:https : //github.com/rust-lang/rust/issues/32966