一、常用trait
Clone&Copy
pub trait Clone: Sized {
fn clone(&self) -> Self;
}
pub trait Copy: Clone { }
Clone (父trait) | Copy (子trait) | let y = x; | let y = x.clone(); |
发生移动 | 编译报错 | ||
√ | 发生移动 | 发生拷贝 | |
√ | √ | 发生拷贝 | 发生拷贝 |
Clone:可以理解为深拷贝,例如String的clone就是将栈上的指针和堆上的字符都拷贝一份。
若某类型实现了Clone,则y=x仅仅只是移动所有权,若想做深拷贝必须显式调用.clone()
Copy:逐比特拷贝。 因此Copy不能被重载。
若某类型实现了Copy,则y=x就进行的是拷贝而非移动。
若结构体的每个字段都实现了Copy,rust编译器不会自动为该结构体生成Copy trait,即y=x仍然会发生移动。只有加上#[derive(Copy, Clone)]才行。
不可变引用&T也是实现了Copy的。就算T不可Copy,&T也是可Copy的。
可变引用&mut T不可Copy。
实现了Copy就不能实现Drop,实现了Drop就不能实现Copy。
来看一个编译报错:
let s = String::from("haha");
let r = &s;
let s2 = *r;
你可能会以为,由于String只实现了Clone没有实现Copy,则let s2=*r这句理应发生移动。但是由于r是一个引用,引用并不拥有数据的所有权,所以不能通过引用来移动数据。
二、常用类
2.1 array
类型为 [T; N],表示N个T类型元素。初始化方式有以下两种:
let arr1: [u32; 3] = [0; 3]; // 3个0
let arr2: [u32; 3] = [5, 6, 7];
2.2 Vec
类型为Vec<T>,初始化方式有以下几种:
let mut v = Vec::new(); // 此时还不知道T类型
v.push(7); // 现在才知道是i32
let mut v: Vec<u32> = Vec::new();
let mut v = Vec::<u32>::new();
let mut v = Vec::<u32>::with_capacity(3);
let mut v = Vec::from([7, 8, 9]);
let mut v = vec![0; 3];
let mut v = vec![7, 8, 9];
单线程版本 | 多线程版本 | |
Cell<T> 适用于可Copy的类型 set/get/replace | ||
互斥锁 | Mutex<T> lock | |
读写锁 | RefCell<T> 动态的借用规则检查 borrow/borrow_mut | RwLock<T> read/write |
单一所有者 | Box<T> | |
多个所有者 | Rc<T> | Arc<T> |
常见组合 | Rc<Cell<T>> Rc<RefCell<T>> | Arc<Mutex<T>> Arc<RwLock<T>> |
二、遍历
按值遍历(该种方式会将v移动掉,后续无法再使用)
let v = vec![1, 2, 3, 4, 5];
for x in v { // 等价于v.into_iter()。 x是i32类型
println!("{x}");
}
按不可变引用遍历:
let v = vec![1, 2, 3, 4, 5];
for x in &v { // 等价于v.iter()。 x是&i32类型
println!("{x}");
}
按可变引用遍历:
let mut v = vec![1, 2, 3, 4, 5];
for x in &mut v { // 等价于v.iter_mut()。 x是&mut i32类型
println!("{x}");
}
三、HashMap
use std::collections::HashMap;
// 用new创建HashMap
let mut map: HashMap<String, i32> = HashMap::new();
// 插入key-value
map.insert(String::from("hello"), 3);
// 用key找value, 注意返回值是Option<&V>
let found: Option<&i32> = map.get(&String::from("hello"));
// 需要先unwrap得到&V,再用*解引用
let value: i32 = *found.unwrap();
四、Box和Any
use std::any::Any;
let p: Box<dyn Any> = Box::new(5);
// Box<dyn Any>具有downcast方法,消耗自身,转换为Result
// 转换成功时是Box<T>,转换失败时仍然保持Box<dyn Any>
let down1: Result<Box<i32>, Box<dyn Any>> = p.downcast::<i32>();
// Any具有downcast_ref方法,返回Option<&T>
let down2: Option<&i32> = p.downcast_ref::<i32>();
let value = *down2.unwrap();
五、标准库的工程组织结构
std
├── Cargo.toml
└── src
├── lib.rs (pub mod thread; pub mod collections; pub mod alloc; pub use core::any;)
├── thread
├── mod.rs (mod tests; mod scoped; pub struct Builder; )
├── tests.rs
├── scoped.rs
├── collections
├── mod.rs (mod hash; )
├── hash
├── mod.rs (pub mod map; pub mod set;)
├── alloc.rs