自学内容网 自学内容网

趣谈 Rust 的 Copy trait 和 Clone trait

一、Copy trait 的关键作用

Rust 程序中的变量可以分成两类:实现 Copy trait 的和没实现 Copy trait 的。这有啥区别?当然很重要!

  • 实现 Copy trait 的变量: 不存在所有权问题,可以随意赋值给其他变量,可以随意当参数传递给函数。因为每次赋值或函数传参数,实现 Copy trait 的变量都是把自己的一个完整的拷贝给了别人,而自身不因此受任何牵连和副作用影响。Rust 的整数、浮点数等简单数据类型,都是实现 Copy trait 的。
  • 未实现 Copy trait 的变量: 这类变量内部一般都有指针或变量引用,如果把这样的变量赋值给其他变量,当前变量就会失去所有权。因此,这类变量需要接受所有权、生命周等期机制来进行有效管理。

二、我的数据类型需要实现 Copy trait 吗?

如果你的数据类型包含数据量较大,而且你用内部的指针指向这些大的数据块,那么你完整复制这样的变量需要很大的代价,这种情况下,建议不要实现 Copy trait。因为在代码中,赋值语句、函数调用等场合,一不小心就会触发 copy 操作,影响程序效率。

相反,你可以利用 clone 方法显式复制变量。

三、Clone trait

Clone 与 Copy 都是复制当前变量,产生一个副本,二者的差别在于 Rust 语法或语义。Clone方法表明可以用显式的方法产生一个变量的副本,这一般意味着当前变量内部可能有指针,部分数据可能在堆上分配。同时也常常意味着这类变量的使用存在所有权转移问题。

clone 和 copy 这两种方法的实现代码,没有什么区别,区别就在于 Rust 的语法和语义方面。

四、包含指针的数据类型一定不能实现 Copy 操作吗?

一般来讲是这样的,但不排除特殊需要。

为便于理解这个问题,我们先看一个例子:

let a = Arc::new(123);
let b = a.clone();

从 Rust 语义上看,a、b 是两个完全独立的变量。从编程的角度看,后续代码认为 a、b 不存在所有权转移问题,他们在存储空间上不存在任何个联系。但是,实际上二者是共享数据的,因为 Arc 是一个共享计数指针。

这个例子告诉我们,如果有必要,可以用一些技巧欺骗 Rust 编译器的。所以我设想,Arc 这样的数据类型,与其不厌其烦地调用 clone 复制数据,倒不如直接实现 Copy trait,这样的话,上面的代码可以写成下面的形式:

let a = Arc::new(123);
let b = a;

注意,如果 Arc 实现了 Copy trait,那么编译器认为 let b = a 只是把数据复制了一个完整、独立的副本,变量 a 中数据的所有权并没有转移。当然,Rust 并没有为 Arc 实现 trait,但我坚信,未来我们一定能看到有 Rust 代码库实现类似的机制。

总结

在 Rust 中,CopyClone 是两个重要的 trait,它们允许开发者复制数据的实例。尽管这两个 trait 都与复制有关,但它们之间有一些重要的区别。

Copy Trait

Copy trait 是一个标记 trait,没有定义任何方法。如果一个类型实现了 Copy,那么它表明该类型的值可以通过简单的位拷贝来复制,而不会导致任何运行时开销或可能的副作用。换句话说,Copy 类型的值在赋值或作为函数参数传递时,不需要显式地调用 .clone() 或其他复制方法,而是可以隐式地、低成本地进行位拷贝。

要实现 Copy trait,一个类型必须满足以下条件:

  1. 类型的所有成员都必须是 Copy 的。
  2. 没有使用到堆分配(例如,不包含 Box, Vec, 或 String 这样的类型)。
  3. 不包含任何形式的可变引用或借用。

由于 Copy 允许隐式复制,所以应该谨慎地为其实现,以避免意外地多次复制可能导致的问题。

Clone Trait

Copy 不同,Clone trait 定义了一个名为 clone 的方法,它返回一个与原始对象具有相同值的新对象。如果一个类型实现了 Clone,那么它可以使用 .clone() 方法来显式地创建一个副本。

Copy 相比,Clone 更加通用和灵活。例如,它可以用于复制那些包含堆上数据的类型,这些数据不能简单地通过位拷贝来复制。

区别

  1. 隐式与显式Copy 是隐式的,而 Clone 需要显式调用 .clone() 方法。
  2. 性能Copy 是低成本的位拷贝,而 Clone 可能涉及更复杂的复制操作,特别是当涉及到堆上数据时。
  3. 限制:不是所有类型都可以实现 Copy,因为它有一些严格的限制。但大多数类型都可以实现 Clone
  4. 用途Copy 主要用于优化和简化代码,而 Clone 提供了一种更通用的复制机制。

总之,当你知道一个类型可以通过简单的位拷贝来安全地复制时,你可以为其实现 Copy。如果你需要一种更通用的复制机制,或者当类型包含堆上数据时,你应该使用 Clone


原文地址:https://blog.csdn.net/quicmous/article/details/137682015

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!