技术标签: rust
Rust 中有两个常见的 trait,Clone 和 Copy,许多初学者没有搞明白。今天我们来专门谈一谈这两个 trait。
Copy 的全名是 std::marker::Copy。请大家注意 std::marker 这个模块里面的所有的 trait 都是特殊的 trait。目前稳定的有四个,它们是 Copy、Send、Sized、Sync。它们的特殊之处在于它们是跟编译器密切绑定的,impl 这些 trait 对编译器的行为有重要影响。在编译器眼里,它们与其它的 trait 不一样。这几个 trait 内部都没有方法,它们的唯一任务是,给类型打一个“标记”,表明它符合某种约定,这些约定会影响编译器的静态检查以及代码生成。
Copy 这个 trait 在编译器的眼里代表的是什么意思呢?简单点总结就是说,如果一个类型 impl 了 Copy trait,意味着任何时候,我们可以通过简单的内存拷贝(C语言的按位拷贝memcpy)实现该类型的复制,而不会产生任何问题。
一旦一个类型实现了 Copy trait,那么它在变量绑定、函数参数传递、函数返回值传递等场景下,它都是 copy 语义,而不再是默认的 move 语义。
并不是所有的类型都可以实现Copy trait。Rust规定,对于自定义类型,只有所有的成员都实现了 Copy trait,这个类型才有资格实现 Copy trait。
常见的数字类型、bool类型、共享借用指针&,都是具有 Copy 属性的类型。而 Box、Vec、可写借用指针&mut 等类型都是不具备 Copy 属性的类型。
对于数组类型,如果它内部的元素类型是Copy,那么这个数组也是Copy类型。
对于tuple类型,如果它的每一个元素都是Copy类型,那么这个tuple会自动实现Copy trait。
对于struct和enum类型,不会自动实现Copy trait。而且只有当struct和enum内部每个元素都是Copy类型的时候,编译器才允许我们针对此类型实现Copy trait。
我们可以认为,Rust中只有 POD(C++语言中的Plain Old Data) 类型才有资格实现Copy trait。在Rust中,如果一个类型只包含POD数据类型的成员,没有指针类型的成员,并且没有自定义析构函数(实现Drop trait),那它就是POD类型。比如整数、浮点数、只包含POD类型的数组等,都属于POD类型。而Box、 String、 Vec等,不能按 bit 位拷贝的类型,都不属于POD类型。但是,反过来讲,并不是所有的POD类型都应该实现Copy trait。
Clone 的全名是 std::clone::Clone。它的完整声明是这样的:
pub trait Clone : Sized {
fn clone(&self) -> Self;
fn clone_from(&mut self, source: &Self) {
*self = source.clone()
}
}
它有两个关联方法,其中 clone_from 是有默认实现的,它依赖于 clone 方法的实现。clone 方法没有默认实现,需要我们手动实现。
clone 方法一般用于“基于语义的复制”操作。所以,它做什么事情,跟具体类型的作用息息相关。比如对于 Box 类型,clone 就是执行的“深拷贝”,而对于 Rc 类型,clone 做的事情就是把引用计数值加1。
虽然说,Rust中 clone 方法一般是用来执行复制操作的,但是你如果在自定义的 clone 函数中做点什么别的工作编译器也没法禁止,你可以根据情况在 clone 函数中编写任意的逻辑。但是有一条规则需要注意:对于实现了 Copy 的类型,它的 clone 方法应该跟 Copy 语义相容,等同于按位拷贝。
绝大多数情况下,实现 Copy Clone 这样的 trait 都是一个重复而无聊的工作。因此,Rust提供了一个 attribute,让我们可以利用编译器自动生成这部分代码。示例如下:
#[derive(Copy, Clone)]
struct MyStruct(i32);
这里的 derive 会让编译器帮我们自动生成 impl Copy 和 impl Clone 这样的代码。自动生成的 clone 方法,就是依次调用每个成员的 clone 方法。
通过 derive 方式自动实现 Copy 和手工实现 Copy 有一丁点的微小区别。当类型具有泛型参数的时候,比如 struct MyStruct<T>{},通过 derive 自动生成的代码会自动添加一个 T: Copy 的约束。
目前,只有一部分固定的特殊 trait 可以通过 derive 来自动实现。将来 Rust 会允许自定义的 derive 行为,让我们自己的 trait 也可以通过 derive 的方式自动实现。
Copy 和 Clone 两者的区别和联系有:
文章浏览阅读1.5k次,点赞2次,收藏6次。有一点需要注意的是,要完成一些步骤才能获得下载资格,选择accept agreement,下一步。下载后,双击进入安装界面,下一步。第一个要选,都选也行,然后下一步。选择要安装的地址,然后下一步。选择Chinese.ptl。再次进入就是正文了。_cisco packet tracer下载
文章浏览阅读9k次。在此之前元素垂直居中我使用的是绝对定位absolute或固定定位fixed如何用flex实现元素垂直居中呢,父级包括子级<div class='itemBox'> <div>boxboxboxboxboxboxboxboxboxboxbox</div></div> .itemBox{display: flex;..._cssdisplayflex居中
文章浏览阅读6.2k次。应用隐藏大师计算器app是一款可以将自己隐私的软件进行隐蔽加密的软件,应用隐藏大师计算器最新版能把自己的图标换成计算器图标,名字也能换成计算器,隐藏应用,隐藏软件或游戏,所有被隐藏的东西都被藏到了这款有着计算机长相和密码的软件中,感兴趣的小伙伴们赶紧来下载应用隐藏大师计算器吧!这是一款把应用隐藏起来的软件,表面上这是一个计算机,实际上这是一个藏宝箱,各位绅士必备,包括照片 视频 什么的都可以在里面..._计算机里藏手机软件
文章浏览阅读1.5w次,点赞12次,收藏43次。SOLIDWORKS 安装教程_solidworks2021序列号
文章浏览阅读4.3k次,点赞6次,收藏8次。PTA-自助扫码题意扫码支付如今已普及应用在大型超市,街边小贩等多个消费支付的场景,刷脸支付也在商超零售场景逐渐应用,很多的大型超市引进自助收银系统,实现自助结账应用。已知某超市有自助收银机m台,每件商品扫码时间都相等,均为1秒,现有n个顾客准备结账,初始顺序已经确定为1-n,编号i号顾客购买的商品件数为ci,当其中某名顾客扫完所有商品后,下一名排队等候付款的顾客马上使用刚空闲的这台自助收银机,即忽略支付时间和自助收银机换人的时间开销,则所有顾客完成结账需要多少时间?pta自动扫码提示:以下是_已知某超市有自助收银机m台,每件商品扫码时间都相等,均为1秒,现有n个顾客准备结账
文章浏览阅读325次。智能手机使用时间越来越长,照片、视频、音乐、应用软件等不断增多。起初,还能把各类文件管理的有条不紊,但随着不断的拷贝、新建、删除,眼看着手机中的文件夹越来越多、越来越复杂,手机中的文件资料也开始像杂货铺一样乱七八糟,直到有一天自己都无法在杂乱的手机文件中找到刚拷贝进去的资料。手机虽然智能了,但文件的管理却没跟的上智能的脚步,对于智能机用户而言,这已经不再是一个小问题。小编就深受文件管理难之苦,不过..._电脑修改手机安卓文件夹失败
文章浏览阅读275次。电脑预装Linux第三方系统怎么破?看外行人重装Win10系统的精准攻略2020-03-10 20:12:2628点赞72收藏82评论创作立场声明:予人点赞,手有余香,欢迎值友们一起交流探讨。一、前言上周女神节,楼主给老婆大人入了一台MagicBook15笔记本电脑,配置为锐龙5处理器+8G内存+512G固态硬盘。而出厂时电脑预装了Linux第三方系统,着实比较鸡肋——主要是楼主为了省钱,购买的此..._电脑第三方linux
文章浏览阅读3.4k次。通信语义为保证RPC语义的实现,我们必须在良种可能中进行选择。一方面,为尽量使远程过程调用的行为像一个本地过程调用,RPC应该使用一种像TCP这样可靠的运输,而且应该对程序员保证可靠性。另一方面,为允许程序员使用高效率的、无连接的运输协议,远程过程调用机制应当支持用UDP这样的数据报协议进行通信。因为UDP传输的不可靠性,在传输过程中可能因为报文的丢失,使得调用者无法做出应答,而导致远程过_sun-rpc发送数据帧
文章浏览阅读251次。1、chrome 已安装插件intercept。 由于chrome安全的限制,发不出带cookie的请求。如果想要发送带cookie的请求,需要开启Interceptor。 2、chrome 浏览器要设置打开,在运行期间浏览器要一直打开。 3、本人是用fiddler对app的请求..._postman 模仿cookie jsessonid
文章浏览阅读915次,点赞2次,收藏2次。前言 项目需要,获取WebRTC封装的VideoFrame中的byte,效率很慢,仅供参考方法 VideoFrame自带转I420的接口,转I420后,根据格式去除Y,U,V各分量,然后拷贝到数组中(通过实现onFrame接口,然后addSink实现接口的对象获取到VideoFrame)代码public void onFrame(VideoFrame var1) { VideoFrame.I420Buffer buffer = v..._i420buffer转byte数组
文章浏览阅读422次。Linux Programmer's Manual & User Commandshttps://www.kernel.org/doc/man-pages/ 搜索框输入epoll调用搜索引擎查找在线搜索查看man手册(比如查epoll),可以直接收藏,方便下次点击搜索:http://global.bing.com/search?q=site:man7.org epollThe Linux ..._fmax c++ linux手册页
文章浏览阅读1.5k次。本章要点:Ø 用户帐号和组概述Ø 创建和管理用户帐号Ø 在域中使用组的策略3.1 用户帐号和组概述活动目录是一种保存和维护网络资源所需的数据的目录服务数据库。域用户帐号在AD中创建一次,就能在域中的工作站上登录访问网络资源。组通常是用户帐号的集合,可以用来高效管理域资源的访问。管理对 Active Directory 目录服务拥有管理权限的用户和组是网络系统保护的重要组成部分。获得 Active ..._用户和组管理的作用