Rust中的Copy和Clone

Posted Pomelo_刘金

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Rust中的Copy和Clone相关的知识,希望对你有一定的参考价值。

1.Copy和Clone

Rust中的CopyClonetrait都允许创建类型实例的副本。它们都提供了一种复制类型实例的方法,但它们之间存在一些重要的区别。了解这些区别有助更好地使用这两个特征。

2. Copytrait

Copytrait允许按位复制类型的实例。这意味着当您将一个变量赋值给另一个变量时,如果该类型实现了Copytrait,则会创建一个新的副本。这与移动语义不同,其中原始变量不再可用。

要使用derive属性为类型自动生成Copytrait的实现,只需在类型定义之前添加#[derive(Copy)]即可。例如:

#[derive(Copy)]
struct Point 
    x: i32,
    y: i32,

复制代码

请注意,并非所有类型都可以实现Copytrait。例如,具有堆分配字段(如StringVec<T>)的类型不能实现Copy

3. Clonetrait

与之相反,Clonetrait提供了一个clone方法,用于创建类型实例的深层副本。这意味着即使类型具有堆分配字段(如StringVec<T>),也可以实现Clonetrait。

要为类型自动生成Clonetrait的实现,只需在类型定义之前添加#[derive(Clone)]即可。例如:

#[derive(Clone)]
struct Point 
    x: i32,
    y: i32,

复制代码

但是,并非所有类型都可以使用derive属性自动生成Clonetrait的实现。如果类型的某些字段没有实现

4. CopyClonetrait之间的区别

尽管CopyClonetrait都允许您创建类型实例的副本,但它们之间存在一些重要的区别。

首先,当您使用赋值语句复制一个实现了Copytrait的类型时,复制操作是隐式执行的。而当您使用clone方法复制一个实现了Clonetrait的类型时,复制操作是显式执行的。 例如:

#[derive(Copy)]
struct Point 
    x: i32,
    y: i32,

fn main() 
let p1 = Point  x: 1, y: 2 ;
let p2 = p1
assert_eq!(p1.x, p2.x);
assert_eq!(p1.y, p2.y); 

复制代码
#[derive(Clone)]
struct Point 
    x: i32,
    y: i32,


fn main() 
    let p1 = Point  x: 1, y: 2 ;
    let p2 = p1.clone();
    assert_eq!(p1.x, p2.x);
    assert_eq!(p1.y, p2.y);

复制代码

此外,这两个trait分别适用于不同的场景。对于那些具有简单按位复制语义的类型(如标量类型和由它们组成的数组和元组),使用Copytrait更为方便。而对于那些需要执行深层复制操作的类型(如具有堆分配字段的类型),则应使用Clonetrait。from刘金,转载请注明原文链接。感谢!

 

Rust如何尊重复制特性?

[如果您使一个结构派生Copy特性,那么Rust将在以下代码中将y复制为x,而不是从x移至y

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

let x = Foo;

let y = x;

[如果我使用C ++,我会说Copy以某种方式使Foo实现了=运算符,其方式是在右侧复制整个对象。

在Rust中,是否只是在编译器中将其简单地实现为规则?当编译器找到let y=x时,它仅检查复制特征是否派生,并确定复制还是移动?

我对Rust内部有兴趣,因此我可以更好地理解该语言。教程中找不到此信息。

答案

是,这是直接在编译器中实现的。

它会影响本来会移动项目的任何情况,因此它还会影响将参数传递给函数或在match表达式中进行匹配-基本上是涉及模式匹配的任何情况。这样,它实际上不能与用C ++实现=运算符相提并论。

Copy特性的定义是marked as a "lang" item in the source code of the standard library。编译器知道标记为#[lang = "copy"]的项目是决定是否移动或复制类型的特征。编译器还知道一些隐式Copy类型的规则,例如仅包含Copy项的闭包或元组。

另一答案

在Rust中,是否只是在编译器中将其简单地实现为规则?当编译器找到let y = x时,它仅检查复制特征是否派生,并确定复制还是移动?

另一答案

如果要深入研究此代码的编译方式,可以查看运动场中的MIR表示形式。在这个稍微简化的版本中:

以上是关于Rust中的Copy和Clone的主要内容,如果未能解决你的问题,请参考以下文章

将结构与 rust 中的浮点数进行比较

Rust如何尊重复制特性?

torch中的copy()和clone()

如何在不使用复制或克隆的情况下克隆Rust中的结构?

Clone() vs Copy constructor-在java中推荐[重复]

Rust 所有权