---
title: 泛型与单态化
url: https://doc.liz6.com/rust/03-advanced-generics-and-traits/01-generics-and-monomorphization
locale: zh
area: rust
tags:
- rust
- 泛型与Trait进阶
date: 2026-06-30
modified: 2026-06-30
description: Rust 泛型的核心机制是单态化——编译期为每种具体类型参数生成一份独立的机器码。这意味着 Vec 和 Vec 是两套完全不同的函数体,零运行时开销,代价是二进制膨胀。const generics 把常量值也纳入泛型参数,specialization 允许为特定类型提供更优实现(目前 nightly only)。
---

# 泛型与单态化

> Rust 泛型的核心机制是单态化——编译期为每种具体类型参数生成一份独立的机器码。这意味着 `Vec<i32>` 和 `Vec<String>` 是两套完全不同的函数体,零运行时开销,代价是二进制膨胀。const generics 把常量值也纳入泛型参数,specialization 允许为特定类型提供更优实现(目前 nightly only)。

## Monomorphization: 编译期为每个具体类型生成代码

Rust 泛型不是运行时的多态（没有 vtable）——编译器对每个使用泛型的具体类型生成独立的机器码：

```rust
fn max<T: PartialOrd>(a: T, b: T) -> T { if a > b { a } else { b } }

let _ = max(1, 2);                   // 编译器生成 max_i32
let _ = max(1.0, 2.0);              // 编译器生成 max_f64
let x = "a"; let y = "b";
let _ = max(x, y);                  // 编译器生成 max_&str
// 输出 binary 中有 3 份独立的 max 函数, 每份针对具体类型优化
```

这与 C++ 模板的机制相同——都是编译期代码生成。但在 Rust 中，泛型**在定义时就被检查**（不需要等到实例化），所以错误信息更清晰。C++ 模板的错误通常在实例化时爆出，导致几十行的模板错误。

## "零成本抽象"的含义

release build 中，泛型函数通常被**内联**到调用点——最终汇编中看不到泛型函数的存在，只剩几条直接操作 `i32` 或 `f64` 的 `cmp` 指令。这就是 Rust 所谓的"zero-cost abstraction"：你能用高层抽象，但编译后的代码和手写针对具体类型的代码一样快。

## 代码膨胀与缓解

每个具体类型生成一份代码 → 大量类型组合 → 编译时间爆炸 + binary 膨胀。经典缓解策略：**提取非泛型 inner 函数**：

```rust
fn process<T: Display>(items: &[T]) {
    for item in items {
        // 泛型部分: 转成 String (每个 T 调用不同的 Display::fmt)
        let s = item.to_string();
        // 非泛型部分: 后续逻辑不依赖 T
        process_inner(&s);           // 只编译一次
    }
}
fn process_inner(s: &str) { ... }    // 不依赖 T → 不分叉
```

关键：把必须泛型的部分（类型转换）和可以用 trait object 或具体类型处理的部分（业务逻辑）分离。

## Const Generics: 值作为泛型参数

传统泛型参数是类型。const generics (Rust 1.51+) 让**值**也成为泛型参数——编译期常量：

```rust
struct Buffer<T, const N: usize> { data: [T; N] }

let b1: Buffer<i32, 4> = Buffer { data: [1, 2, 3, 4] };
let b2: Buffer<i32, 8> = Buffer { data: [1; 8] };
// b1 和 b2 是**不同类型**! 不能互相赋值
```

主要用途：固定大小的 array/vector、SIMD lanes、编译期 assert array size。

## Specialization (nightly, 尚未 stable)

当前 stable Rust 不支持 trait specialization——你不能为一个 trait 提供"更具体的 impl 覆盖更泛的 impl"。这限制了某些性能优化（如为 `Vec<u8>` 提供比泛型 `Vec<T>` 更高效的 `Extend` impl）。nightly 上有 `min_specialization` 可用，但 stable 上还没有。目前替代方案是用 newtype pattern 提供特化。

## 参考

- **Rust Book**: Chapter 10.1
- **Rust Reference**: Const generics
- **RFC 2000**: Const generics; **RFC 1210**: Specialization

*Keywords: monomorphization, zero-cost abstraction, code bloat, const generics, specialization*
