趣谈 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 中,Copy
和 Clone
是两个重要的 trait,它们允许开发者复制数据的实例。尽管这两个 trait 都与复制有关,但它们之间有一些重要的区别。
Copy Trait
Copy
trait 是一个标记 trait,没有定义任何方法。如果一个类型实现了 Copy
,那么它表明该类型的值可以通过简单的位拷贝来复制,而不会导致任何运行时开销或可能的副作用。换句话说,Copy
类型的值在赋值或作为函数参数传递时,不需要显式地调用 .clone()
或其他复制方法,而是可以隐式地、低成本地进行位拷贝。
要实现 Copy
trait,一个类型必须满足以下条件:
- 类型的所有成员都必须是
Copy
的。 - 没有使用到堆分配(例如,不包含
Box
,Vec
, 或String
这样的类型)。 - 不包含任何形式的可变引用或借用。
由于 Copy
允许隐式复制,所以应该谨慎地为其实现,以避免意外地多次复制可能导致的问题。
Clone Trait
与 Copy
不同,Clone
trait 定义了一个名为 clone
的方法,它返回一个与原始对象具有相同值的新对象。如果一个类型实现了 Clone
,那么它可以使用 .clone()
方法来显式地创建一个副本。
与 Copy
相比,Clone
更加通用和灵活。例如,它可以用于复制那些包含堆上数据的类型,这些数据不能简单地通过位拷贝来复制。
区别
- 隐式与显式:
Copy
是隐式的,而Clone
需要显式调用.clone()
方法。 - 性能:
Copy
是低成本的位拷贝,而Clone
可能涉及更复杂的复制操作,特别是当涉及到堆上数据时。 - 限制:不是所有类型都可以实现
Copy
,因为它有一些严格的限制。但大多数类型都可以实现Clone
。 - 用途:
Copy
主要用于优化和简化代码,而Clone
提供了一种更通用的复制机制。
总之,当你知道一个类型可以通过简单的位拷贝来安全地复制时,你可以为其实现 Copy
。如果你需要一种更通用的复制机制,或者当类型包含堆上数据时,你应该使用 Clone
。
相关文章:
趣谈 Rust 的 Copy trait 和 Clone trait
一、Copy trait 的关键作用 Rust 程序中的变量可以分成两类:实现 Copy trait 的和没实现 Copy trait 的。这有啥区别?当然很重要! 实现 Copy trait 的变量: 不存在所有权问题,可以随意赋值给其他变量,可以随意当参数…...

02 - Git 之命令 +
1 Git相关概念 1.1 以下所谈三个区,文件并不只是简单地在三个区转移,而是以复制副本的方式转移 使用 Git 管理的项目,拥有三个区域,分别是 Working area工作区(亦称为 工作树Working Tree)、stage area …...

每日一练(力扣)
我的思路是暴力枚举: 情况1:相同,就让子串和原串同时后移继续比较 情况2:不相同,就只让原串后移 public int strStr(String haystack, String needle) {if (haystack.length() < needle.length()){return -1;}for (int i 0; i < h…...

JWT详解及实战教程
目录 1.什么是JWT 2.JWT能做什么 3.为什么是JWT 基于传统的Session认证 基于JWT认证 4.JWT的结构是什么? 5.使用JWT 6.封装工具类 7.整合springboot 1.什么是JWT JSON Web Token (JWT) is an open standard (RFC 7519) that defines a compact and self-contained way…...

vue通过echarts实现数据可视化
1、安装echarts cnpm install echarts -Sechart官方图表示例大全:https://echarts.apache.org/examples/zh/index.html#chart-type-line 2、代码实现 <template><div><div class"box" ref"zhu"></div><div class&…...
react17中使用setState导致了死循环
在使用setState时发生死循环的错误,可能的原因是在这三个地方使用了setState: componentDidUpdate;componentWillUpdate;render。 为什么会这样? 每次渲染页面的时候就会调用render,render里面是setState࿰…...

2024年P气瓶充装证模拟考试题库及P气瓶充装理论考试试题
题库来源:安全生产模拟考试一点通公众号小程序 2024年P气瓶充装证模拟考试题库及P气瓶充装理论考试试题是由安全生产模拟考试一点通提供,P气瓶充装证模拟考试题库是根据P气瓶充装最新版教材,P气瓶充装大纲整理而成(含2024年P气瓶…...
Python学习笔记(一)
一、简述实例属性与类属性的区别以及实例方法与类方法的区别 (一)实例属性与类属性 1、实例属性是定义在类的内部,是每个类都共有的属性;2、实例属性是属于对象的,每个对象的可以根据自己的需要不一样,生…...

记一次http访问超时服务器端调试
问题:http访问服务器时没有返回,没有超时,一直在阻塞 处理过程:telnet端口能连上,服务端程序也不存在处理时间过长的情况。 说明tcp连接没问题。推测是客户端连接后再发起请求,服务端阻塞了。因为很多客户…...

C/C++内存泄漏及检测
“该死系统存在内存泄漏问题”,项目中由于各方面因素,总是有人抱怨存在内存泄漏,系统长时间运行之后,可用内存越来越少,甚至导致了某些服务失败。内存泄漏是最难发现的常见错误之一,因为除非用完内存或调用…...

跟TED演讲学英文:Why AI will spark exponential economic growth by Cathie Wood
TED英文文稿 文章目录 TED英文文稿Why AI will spark exponential economic growthIntroductionVocabularyTranscriptSummary后记 Why AI will spark exponential economic growth Link: https://www.ted.com/talks/cathie_wood_why_ai_will_spark_exponential_economic_growth…...

常用组合逻辑电路模块(4):数值比较器
数值比较器概述 在数字系统中,特别是在计算机中,常需要对两个数的大小进行比较。而数值比较器就是对两个二进制数A、B进行比较的逻辑电路。 比较结果有A>B、A=B、A<B三种情况。 简单数值比较器 1位数值比较器&#…...

实时时钟模块RX8901CE具有数字温度补偿功能,助力工业设备实现精准控制
在工业控制领域,电子产品的工作温度范围较广,同样的产品将面对高温、低温等不同工况。对于时钟信号敏感的电路设计而言,温度变化将严重影响产品功能,因此需要高精度时钟来保证电路信号的稳定,这种情况下需要使用带数字…...

Acrobat Pro DC 2023 for mac直装激活版 pdf编辑处理工具
Acrobat Pro DC 2023 for Mac是一款功能强大的PDF编辑器,为用户提供了全面且高效的PDF处理体验。 软件下载:Acrobat Pro DC 2023 for mac直装激活版下载 首先,它支持用户从现有文档创建PDF,或者将其他文件格式如图片、网页等轻松转…...

3D应用模型信创系统实时渲染有什么要求?
实时云渲染技术是数字孪生领域,比较常用的轻量化软件交付方式,该技术是将3D应用等大模型的算力执行放在了服务器端,而服务器目前比较常用的还是Windows系统。但随着国产信创在数字孪生领域应用越来越多,实时云渲染平台的国产信创化…...

Flutter之TabBar篇
总结了一下项目中用到的几种TabBar,针对不同的样式,有采用系统提供的,也有三方插件提供的,也有自定义的,效果如下(后续如果遇到新的样式,会不间断地记录更新,避免重复造轮子…&#…...

VRRP(虚拟路由冗余协议)详解
VRRP-------虚拟路由冗余协议 在一个网络中,要做为一个合格的网络首先就要具备几种冗余,增加网络的可靠性。 这几种冗余分别为:线路冗余,设备冗余,网关冗余,UPS冗余 VRRP该协议就是解决网关冗余的。在二层…...

【数据结构】04串
串 1. 定义2. 串的比较3. 串的存储结构4. 具体实现5. 模式匹配5.1 常规思路实现5.2 KMP模式匹配算法5.2.1 next数组计算5.2.1 代码计算next数组5.2.2 KMP算法实现 1. 定义 串(string)是由零个或多个字符组成的有限序列,又叫字符串。 一般记为s a 1 , a 2 , . . . ,…...
LAMMPS如何识别多孔结构的孔隙及其大小
关注 M r . m a t e r i a l , \color{Violet} \rm Mr.material\ , Mr.material...

JavaScript ECMAScript标准的与时俱进:从ES6至ES14的革新之路与关键技术特性剖析
ECMAScript(通常缩写为ES)是一种标准化的脚本语言规范,由ECMA International(前身为European Computer Manufacturers Association,欧洲计算机制造商协会)制定。自1997年发布首个版本以来,ECMAS…...

【人工智能】神经网络的优化器optimizer(二):Adagrad自适应学习率优化器
一.自适应梯度算法Adagrad概述 Adagrad(Adaptive Gradient Algorithm)是一种自适应学习率的优化算法,由Duchi等人在2011年提出。其核心思想是针对不同参数自动调整学习率,适合处理稀疏数据和不同参数梯度差异较大的场景。Adagrad通…...
pam_env.so模块配置解析
在PAM(Pluggable Authentication Modules)配置中, /etc/pam.d/su 文件相关配置含义如下: 配置解析 auth required pam_env.so1. 字段分解 字段值说明模块类型auth认证类模块,负责验证用户身份&am…...

全球首个30米分辨率湿地数据集(2000—2022)
数据简介 今天我们分享的数据是全球30米分辨率湿地数据集,包含8种湿地亚类,该数据以0.5X0.5的瓦片存储,我们整理了所有属于中国的瓦片名称与其对应省份,方便大家研究使用。 该数据集作为全球首个30米分辨率、覆盖2000–2022年时间…...

MMaDA: Multimodal Large Diffusion Language Models
CODE : https://github.com/Gen-Verse/MMaDA Abstract 我们介绍了一种新型的多模态扩散基础模型MMaDA,它被设计用于在文本推理、多模态理解和文本到图像生成等不同领域实现卓越的性能。该方法的特点是三个关键创新:(i) MMaDA采用统一的扩散架构…...

Module Federation 和 Native Federation 的比较
前言 Module Federation 是 Webpack 5 引入的微前端架构方案,允许不同独立构建的应用在运行时动态共享模块。 Native Federation 是 Angular 官方基于 Module Federation 理念实现的专为 Angular 优化的微前端方案。 概念解析 Module Federation (模块联邦) Modul…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...

分布式增量爬虫实现方案
之前我们在讨论的是分布式爬虫如何实现增量爬取。增量爬虫的目标是只爬取新产生或发生变化的页面,避免重复抓取,以节省资源和时间。 在分布式环境下,增量爬虫的实现需要考虑多个爬虫节点之间的协调和去重。 另一种思路:将增量判…...
JavaScript 数据类型详解
JavaScript 数据类型详解 JavaScript 数据类型分为 原始类型(Primitive) 和 对象类型(Object) 两大类,共 8 种(ES11): 一、原始类型(7种) 1. undefined 定…...
GitHub 趋势日报 (2025年06月06日)
📊 由 TrendForge 系统生成 | 🌐 https://trendforge.devlive.org/ 🌐 本日报中的项目描述已自动翻译为中文 📈 今日获星趋势图 今日获星趋势图 590 cognee 551 onlook 399 project-based-learning 348 build-your-own-x 320 ne…...

永磁同步电机无速度算法--基于卡尔曼滤波器的滑模观测器
一、原理介绍 传统滑模观测器采用如下结构: 传统SMO中LPF会带来相位延迟和幅值衰减,并且需要额外的相位补偿。 采用扩展卡尔曼滤波器代替常用低通滤波器(LPF),可以去除高次谐波,并且不用相位补偿就可以获得一个误差较小的转子位…...