rust学习笔记

本文介绍了Rust中的Clone和Copy特质,区分了深拷贝和移动行为,强调了结构体实现Copy的条件,并讲解了不同方式的遍历及其影响。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、常用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

    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值