简体   繁体   English

Rust 如何尊重 Copy 特征?

[英]How does Rust respect the Copy trait?

If you make a struct derive the Copy trait then Rust is going to make y as a copy of x in the code below, as opposed to moving from x to y otherwise:如果您使结构派生Copy特征,则 Rust 将使y在下面的代码中作为x的副本,而不是从x移动到y否则:

#[derive(Debug, Copy, Clone)]
struct Foo;

let x = Foo;

let y = x;

If I were in C++ I'd say that Copy somehow makes Foo implement the = operator in a way that it copies the entire object on the right side.如果我在 C++ 中,我会说Copy以某种方式使Foo实现=运算符,从而在右侧复制整个 object 。

In Rust, is it simply implemented as a rule in the compiler?在Rust中,是不是简单的在编译器中实现为规则? When the compiler finds let y=x it simply checks if the Copy trait is derived or not and decides if copy or moves?当编译器找到let y=x时,它只是检查 Copy 特征是否派生并决定是复制还是移动?

I'm intersted in Rust internals so I can understand the language better.我对 Rust 内部结构很感兴趣,所以我可以更好地理解语言。 This information can't be found on tutorials.在教程中找不到此信息。

In Rust, is it simply implemented as a rule in the compiler?在Rust中,是不是简单的在编译器中实现为规则? When the compiler finds let y=x it simply checks if the Copy trait is derived or not and decides if copy or moves?当编译器找到 let y=x 时,它只是检查 Copy 特征是否派生并决定是复制还是移动?

At runtime, there is no semantic difference (though the applicable optimisations might vary), both move and copy are just a memcopy , and in either case the copy can be optimised away.在运行时,没有语义差异(尽管适用的优化可能会有所不同), move 和 copy 都只是一个memcopy ,并且在任何一种情况下,副本都可以被优化掉。

At compile-time, the compile is indeed aware of the Copy / !Copy distinction: in the case where x would be a !Copy type the assignment "consumes" the variable, meaning you can't use it afterwards.在编译时,编译确实知道Copy / !Copy的区别:在x将是!Copy类型的情况下,赋值“消耗”变量,这意味着您以后不能使用它。

If the item is Copy then it doesn't and you can.如果该项目是Copy ,那么它不是,你可以。

That's about it.就是这样。

Yes, this is directly implemented in the compiler.是的,这是直接在编译器中实现的。

It affects any situation that would otherwise move the item, so it also affects passing parameters to functions or matching in a match expression – basically any situation that involves pattern matching.它会影响任何会移动项目的情况,因此它也会影响将参数传递给函数或匹配表达式中的match ——基本上是任何涉及模式匹配的情况。 In that way, it's not really comparable to implementing the = operator in C++.这样一来,它就无法与在 C++ 中实现=运算符相比。

The definition of the Copy trait is marked as a "lang" item in the source code of the standard library . Copy trait 的定义在标准库的源代码中被标记为“lang”项 The compiler knows that the item marked with #[lang = "copy"] is the trait that decides whether a type is moved or copied.编译器知道用#[lang = "copy"]标记的项目是决定一个类型是移动还是复制的特征。 The compiler also knows some ruls about types that are implicitly Copy , like closures or tuples that only contain items that are Copy .编译器还知道一些关于隐式Copy类型的规则,例如仅包含Copy项的闭包或元组。

If you want to dig into how this code is compiled, you could take a look at the MIR representation in the playground.如果您想深入了解这段代码是如何编译的,您可以查看 Playground 中的 MIR 表示。 In this slightly simplified version:在这个稍微简化的版本中:

#[derive(Copy, Clone)]
struct Foo;

fn main() {
    let x = Foo;

    let y = x;
}

the slightly trimmed MIR output is:略微修剪的 MIR output 是:

    bb0: {
        StorageLive(_1);
        _1 = const Scalar(<ZST>): Foo;

        StorageLive(_2);
        _2 = const Scalar(<ZST>): Foo;

        StorageDead(_2);
        StorageDead(_1);
        return;
    }

So in this specific case, the compiler has determined that Foo is a Zero Sized Type (ZST) for x and y (here, _1 and _2 ), so both are assigned a constant empty value, so there isn't any copying as-such.因此,在这种特定情况下,编译器已确定Fooxy (此处为_1_2 )的零大小类型(ZST),因此两者都被分配了一个恒定的空值,因此没有任何复制作为-这样的。

To see it in the playground, click here then select "MIR" from the drop down triple dots button just to the right of the "Run" button.要在操场上查看它, 请单击此处,然后单击“运行”按钮右侧的下拉三点按钮中的 select“MIR”。 For more in depth information about MIR, take a look at the rustc dev guide .有关 MIR 的更多详细信息,请查看rustc 开发指南

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM