在 Rust 的语境里,“廉价(cheap)”和“昂贵(expensive)”并不是指代码写得难不难,而是指运行时开销的高低——CPU 指令、内存分配、系统调用的多少。
一句话总结:
廉价操作 ≈ 只做指针/位运算,不分配内存;昂贵操作 ≈ 可能触发堆分配、系统调用或大段数据复制。
1. 廉价操作(Cheap)
| 动作 | 背后发生了什么 | 例子 |
|---|---|---|
| 取引用 | 只是把地址放进寄存器 | &v[0] |
类型强转(as) | 按位重解释,无运算 | u32 as i32 |
| 切片 | 新建一个胖指针(ptr + len) | &v[1..3] |
as_str() / as_slice() | 返回内部指针,零拷贝 | String::as_str |
len() / is_empty() | 读字段,O(1) | Vec::len |
关键词:不分配、不复制、不 syscall。
2. 昂贵操作(Expensive)
| 动作 | 背后发生了什么 | 例子 |
|---|---|---|
| 堆分配 | 向操作系统要内存、初始化元数据 | String::from("…") |
| 深拷贝 | 遍历整块数据再写一份 | vec.clone() |
| 系统调用 | 进入内核态,上下文切换 | File::open |
| 大计算 | O(n) 或更差的算法 | (0..1_000_000).sum() |
关键词:可能触发 alloc、syscall、O(n) 复制或计算。
3. 为什么 Rust 文档常提 “cheap”?
- 零成本抽象原则:
as_str()这类函数保证不会隐藏额外开销,可以放心在热路径里调用。 - 优化提示:当你看到
to_owned()、clone()或into_string()时,立刻意识到这里可能会变慢,需要评估是否在循环或高频代码里使用。
4. 速记口诀
“廉价就是只玩指针,昂贵就要动内存。”