趣谈 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…...
【Axure高保真原型】引导弹窗
今天和大家中分享引导弹窗的原型模板,载入页面后,会显示引导弹窗,适用于引导用户使用页面,点击完成后,会显示下一个引导弹窗,直至最后一个引导弹窗完成后进入首页。具体效果可以点击下方视频观看或打开下方…...
ssc377d修改flash分区大小
1、flash的分区默认分配16M、 / # df -h Filesystem Size Used Available Use% Mounted on /dev/root 1.9M 1.9M 0 100% / /dev/mtdblock4 3.0M...
MySQL 8.0 OCP 英文题库解析(十三)
Oracle 为庆祝 MySQL 30 周年,截止到 2025.07.31 之前。所有人均可以免费考取原价245美元的MySQL OCP 认证。 从今天开始,将英文题库免费公布出来,并进行解析,帮助大家在一个月之内轻松通过OCP认证。 本期公布试题111~120 试题1…...
C++ Visual Studio 2017厂商给的源码没有.sln文件 易兆微芯片下载工具加开机动画下载。
1.先用Visual Studio 2017打开Yichip YC31xx loader.vcxproj,再用Visual Studio 2022打开。再保侟就有.sln文件了。 易兆微芯片下载工具加开机动画下载 ExtraDownloadFile1Info.\logo.bin|0|0|10D2000|0 MFC应用兼容CMD 在BOOL CYichipYC31xxloaderDlg::OnIni…...
企业如何增强终端安全?
在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...
鸿蒙DevEco Studio HarmonyOS 5跑酷小游戏实现指南
1. 项目概述 本跑酷小游戏基于鸿蒙HarmonyOS 5开发,使用DevEco Studio作为开发工具,采用Java语言实现,包含角色控制、障碍物生成和分数计算系统。 2. 项目结构 /src/main/java/com/example/runner/├── MainAbilitySlice.java // 主界…...
在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案
这个问题我看其他博主也写了,要么要会员、要么写的乱七八糟。这里我整理一下,把问题说清楚并且给出代码,拿去用就行,照着葫芦画瓢。 问题 在继承QWebEngineView后,重写mousePressEvent或event函数无法捕获鼠标按下事…...
Git 3天2K星标:Datawhale 的 Happy-LLM 项目介绍(附教程)
引言 在人工智能飞速发展的今天,大语言模型(Large Language Models, LLMs)已成为技术领域的焦点。从智能写作到代码生成,LLM 的应用场景不断扩展,深刻改变了我们的工作和生活方式。然而,理解这些模型的内部…...
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析
Java求职者面试指南:Spring、Spring Boot、Spring MVC与MyBatis技术解析 一、第一轮基础概念问题 1. Spring框架的核心容器是什么?它的作用是什么? Spring框架的核心容器是IoC(控制反转)容器。它的主要作用是管理对…...
python读取SQLite表个并生成pdf文件
代码用于创建含50列的SQLite数据库并插入500行随机浮点数据,随后读取数据,通过ReportLab生成横向PDF表格,包含格式化(两位小数)及表头、网格线等美观样式。 # 导入所需库 import sqlite3 # 用于操作…...
