720 字
4 分钟
泛型
.jpeg)
核心定义
泛型是 Rust 的参数化多态机制,允许在函数、结构体、枚举等中使用类型占位符(如 T
)。编译时会进行单态化(Monomorphization):
- 为每个具体类型生成专用副本
- 消除运行时开销
- 确保类型安全 提供代码复用和抽象能力,同时保持零成本抽象性能。
工作原理
- 编写泛型代码(如
fn foo<T>(v: &[T]) {...}
) - 编译器检测实际调用类型(如
i32
/String
) - 为每个类型生成专用版本(
foo_i32
/foo_String
) - 编译优化消除重复代码
- 最终二进制包含类型特化函数副本
flowchart TD A[定义泛型函数 fn foo] --> B[调用 foo:: ] A --> C[调用 foo:: ] B --> D[生成 foo_i32 特化版本] C --> E[生成 foo_String 特化版本] D & E --> F[编译为机器码]
关键点
- 单态化优势:编译期生成具体类型代码,零运行时开销
- 特质约束:通过
T: Trait
限制泛型类型能力(如T: Clone
) - 性能等同手写:生成的专用代码与手动编写效率相同
- 结构体泛型:
struct Point<T> { x: T, y: T }
- 枚举泛型:
Option<T>
/Result<T, E>
是标准库范例 - 常量泛型:Rust 1.51+ 支持值参数(如
[T; N]
)
常见误区
- 过度泛化:为不必要场景使用泛型增加复杂性
- 特质遗漏:未添加必要约束(如尝试
T + T
但未约束Add
) - 二进制膨胀:过多泛型实例增加编译后体积
- 类型推断失败:复杂泛型需显式标注类型(如
parse::<i32>()
) - 误认动态分发:泛型是静态分发(与
dyn Trait
混淆)
应用场景
场景 | 示例 | 泛型作用 |
---|---|---|
容器类型 | Vec<T> , HashMap<K, V> | 存储任意类型数据 |
算法抽象 | fn sort<T: Ord>(items: &mut [T]) | 为可比较类型提供通用排序 |
错误处理统一 | Result<T, E> | 封装任意成功值/错误类型 |
数学运算 | struct Vector3<T> { x,y,z: T } | 支持 f32/f64/i32 等类型 |
线程安全传递 | `thread::spawn( | |
序列化反序列化 | serde_json::from_str::<T>(s) | 将 JSON 解析为指定类型 |
关联知识
- 特质(Trait):泛型约束的核心机制(
T: Display
) - 生命周期:泛型生命周期参数
<'a>
处理引用有效性 - 单态化(Monomorphization):编译期生成具体类型代码的过程
- 类型推断:编译器自动推导泛型实例化类型
- PhantomData:标记结构体持有泛型类型(即使未直接使用)
- 泛型特化:实验性功能,允许重叠的实现(RFC 1210)
- 常量泛型:值参数化(如数组长度
[T; N]
)
💡 设计哲学:
- 优先使用泛型而非动态分发(
dyn Trait
)保证性能 - 通过特质约束明确类型能力边界
- 注意编译时间和二进制体积的平衡 标准库泛型容器(如
Vec<T>
)是学习的最佳范例!