Drop
- 自定义drop方法在默认销毁前调用执行 
- 如果实现了Drop Trait, 则不能实现Copy Trait. 
- 如果实现了Copy Trait, 则意味这个类型可以通过byte-for-byte复制获得一份独立的数据拷贝, 那么drop两份相同的数据通常是一个错误. 
- std有一个全局的 - drop方法, 比较fancy: 通过参数获得所有权, 然后直接是个空函数, 函数返回就释放了实参的变量.- 1 - fn drop<T>(_x: T) { } 
Sized
- Rust不能在变量里保存unsized的值, 也不能把unsize的值作为参数. 
- 所有固定大小的类型都实现里 - std::marker::Sizedtrait, 这个trait没有任何方法和联合类型(associated type)
- 不能实现自定义的Sized trait. 
- Sized trait只能用于绑定到类型参数, 也就是用于参数的类型声明(及检查), 例如 - T: Sized不能用于其它用途, 这种trait 叫 marker trait
- ?Sized叫 questionably sized, 允许固定大小, 也允许非固定大小类型.
- struct的最后一个字段允许是 - ?Sized类型, 但如果这样, struct本身就变为了unsized.
- 但如果写成泛型, 并传入一个Sized类型, 那么这个类型的struct仍然是Sized. 大小取决于泛型的参数类型: - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14- struct RcBox<T: ?Sized> { 
 rec_count: usize,
 value: T,
 }
 // Sized type
 let boxed_lunch: RcBox<String> = RcBox {
 ref_count: 1,
 value: "lunch".to_string()
 }
 use std::fmt::Display;
 // UnSized type
 let boxed_displayable: &RcBox<Display> = &boxed_lunch;
Clone
- clone方法必须返回和- self独立无关的一份拷贝.
- Clonetrait是Sized的sub-trait, 所以Self类型必须是Sized- 1 
 2
 3
 4
 5
 6- trait Clone: Sized { 
 fn clone(&self) -> Self;
 fn clone_from(&mut self, source: &Self) {
 *self = source.clone()
 }
 }
- 通常情况下clone的成本比较高, 但是对于 - Rc<T>和- Arc<T>这类的类型, Rust的对它们的clone只是简单的增加计数.
- 通常尽可能使用 - clone_from来减少clone开销, 这会允许一些优化. 例如, String的clone, 被赋值的String如果capacity够大, 可以不需要释放内存, 直接把源的内容拷贝过来.
- 如果所有的字段都实现了Clone, 那么 - struct可以加上属性:- #[derive(Clone)]自动实现Clone trait
- clone方法不能失败(infallible), 对于- std::fs::File这样的类型, 有- try_clone方法, 返回- std::io::Result<File>
Copy
- 之前文章有介绍过, 如果数据类型持有一些需要销毁的资源(文件句柄、堆上数据等), 则不允许实现Copy trait. - 1 - trait Copy: Clone { } 
- Rust对于实现了Copy trait的类型进行赋值, 不会Move原变量的数据(所有权), 而是将原对象做浅拷贝一份给目标变量. 例如简单的数据类型 i32等. 
AsRef<T> & Borrow<T>
- AsRef<T>和- Borrow<T一样, 返回的都是引用, 但是有一个区别:- Borrow保证对同一数据类型Borrow出不同的T都有相同哈希值, 而AsRef没有这类保证, 也就是说对于一个String, 下面三个AsRef返回的是三个哈希值不同的引用:- 1 
 2
 3
 4- let s = String::from("/usr/bin/bash"); 
 let ref1: &Path = s.as_ref();
 let ref2: &[u8] = s.as_ref();
 let ref3: &str = s.as_ref();
From and Into
- From和- Into都会获取原变量的所有权, 转换后返回给调用者.
- 二者是相反的过程, 且也是 - Sized的sub-trait:- 1 
 2
 3
 4
 5
 6
 7- trait Into<T>: Sized { 
 fn into(self) -> T;
 }
 trait From<T>: Sized {
 fn from(T) -> Self; // 静态方法
 }
- 如果自定义类型的构造只有一个参数, 那么可以写一个 - from方法实现From- , 然后Rust会自动帮你实现一个Into trait. 
- 这个Trait有个好处可以访问到一些类型的内部数据, 而又不破坏数据原有内容. 例如: String类型不允许直接修改内部的UTF-8字节, 但是通过 - Into<Vec<u8>>, 我们可以对String数据进行其它操作, 如果压缩等等.
ToOwned
- 如果拿到一个类型引用(假设这个类型实现了Clone Trait), 想对它进行 - Clone, 而在引用类型上无法调用- clone, 例如- &str上无法调用- clone, 因为返回的- str不是- Sized类型. 因此需要有个方法获转换到原类型数据拷贝, 从而获取到所有权(注意⚠️, 要求原类型实现Clone Trait, 返回的是clone出来的数据, 是原数据的一份拷贝, 和原数据没有半毛钱关系了).- 1 
 2
 3
 4- trait ToOwned { 
 type Owned: Borrow<Self>;
 fn to_owned(&self) -> Self::Owned;
 }
- 返回的是实现了 - Borrow<Self>的类型. 可以这么理解, 可以从实现了- Borrow<Self>的类型上borrow到- &Self, 那么反过来可以从- &self上获得到原类型数据. 例如:- Vec<T>实现了- Borrow<[T]>的trait, 可以borrow到- &[T], 那么反过来可以从- &[T]的实例获取到一份- Vec<T>类型的拷贝.- Self是- [T], Owned类型是- Vec<T>- 1 
 2- let s: &str = "a"; 
 let ss: String = s.to_owned(); // ss is a new String clone from s(&str)
- 通常实现 - ToOwnedtrait的都是一些borrow出的引用类型, 如- str, 或- [T].
- 而它的联合类型 - Owned通常是可以转换为它的类型, 如- String,- Vec<T>.
Cow
- 上面的 - ToOwned是立即把- borrow来的引用转换生成一份- Owned的拷贝. clone是有开销的, 有时无法确定是要处理引用还是获取所有权.
- 另一方面, Cow实际就是一个智能指针, 实现了写时复制(C*opy-On-Write)*的功能. - 1 
 2
 3
 4
 5
 6- enum Cow<'a, B: ?Sized + 'a> 
 where B: ToOwned
 {
 Borrow(&'a B),
 Owned(<B as ToOwned>::Owned),
 }
- Cow有个 - from方法, 如果Cow拿到是一个普通的共享引用类型, 那么Cow枚举当前值就是- Borrow. 例如, 传入- &[T], 那边B 就是- [T].
- Cow不会自动转为Owned类型. 也就是不会把引用B ( - str或- [T]之类)自动复制出一份. 除非显式调用它的两个方法:- to_mut(): 会调用B 的- to_owned方法, 生成一份拷贝, 枚举值转为- Owned.
- into_owned(): 提取出一份Owned数据, 如果当前是- Borrow也会调用- to_owned转换. 提取意味着这个Cow变量调用后不再可用.
 
下面官方的例子很好解释这一点:
| 1 | use std::borrow::Cow; | 
