Rust泛型编程:从零成本抽象到极致性能

1. 为什么要用泛型

  • 同一套逻辑处理不同类型数据,避免为每种类型重复写函数
  • 减少冗余代码,提升表达能力,是一种多态实现

无泛型(啰嗦版)

rust 复制代码
fn add_i8(a:i8, b:i8) -> i8 { a + b }
fn add_i32(a:i32, b:i32) -> i32 { a + b }
fn add_f64(a:f64, b:f64) -> f64 { a + b }

泛型版(简洁但不能直接编译,需约束)

rust 复制代码
fn add<T>(a:T, b:T) -> T {
    a + b
}

2. 泛型基础语法

  • T 是泛型参数名(惯例用 T=Type)
    • 使用前必须先声明<T>·
rust 复制代码
fn largest<T>(list: &[T]) -> T { ... }

3. 关键:泛型约束(Trait Bound)

不是所有类型都支持比较、加减,必须用 Trait 限制 T 的行为。

① 比较约束(取最大值)

rust 复制代码
fn largest<T: PartialOrd>(list: &[T]) -> &T {
    let mut largest = &list[0];
    for item in list {
        if item > largest {
            largest = item;
        }
    }
    largest
}

② 加法约束

rust 复制代码
fn add<T: std::ops::Add<Output = T>>(a:T, b:T) -> T {
    a + b
}

4. 显式指定泛型类型

编译器无法自动推断时,用 ::<类型> 手动指定:

rust 复制代码
use std::fmt::Display;

fn create_and_print<T>() where T: From<i32> + Display {
    let a: T = 100.into();
    println!("a is: {}", a);
}

fn main() {
    create_and_print::<i64>(); // 显式指定 T=i64
}

5. 结构体泛型

单泛型(同类型字段)

rust 复制代码
struct Point<T> {
    x: T,
    y: T,
}
// x、y 必须同类型
let p = Point { x: 1, y: 2 }; 

多泛型(不同类型字段)

rust 复制代码
struct Point<T, U> {
    x: T,
    y: U,
}
// x 整数,y 浮点,正常使用
let p = Point { x: 1, y: 1.1 };

6. 枚举泛型(标准库核心)

Option

rust 复制代码
enum Option<T> {
    Some(T),
    None,
}

Result<T, E>(错误处理)

rust 复制代码
enum Result<T, E> {
    Ok(T),
    Err(E),
}

7. 方法中的泛型

为泛型结构体实现方法

rust 复制代码
struct Point<T> { x: T, y: T }

impl<T> Point<T> { // 先声明泛型 T
    fn x(&self) -> &T {
        &self.x
    }
}

方法自带额外泛型

rust 复制代码
impl<T, U> Point<T, U> {
    // V、W 是方法自己的泛型
    fn mixup<V, W>(self, other: Point<V, W>) -> Point<T, W> {
        Point { x: self.x, y: other.y }
    }
}

具体类型实现方法

rust 复制代码
// 只有 f32 类型的 Point 才有此方法
impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

8. Rust 特色:const 泛型(针对值的泛型)

解决不同长度数组是不同类型 的问题,const N: usize 代表数组长度。

rust 复制代码
// T=类型泛型,N=值泛型(数组长度)
fn display_array<T: std::fmt::Debug, const N: usize>(arr: [T; N]) {
    println!("{:?}", arr);
}

fn main() {
    display_array([1,2,3]);
    display_array([1,2]); // 长度不同也可通用
}

9. const fn(编译期执行函数)

允许在编译期计算,常用于配合 const 泛型设置数组 / 缓冲区长度。

rust 复制代码
const fn add(a: usize, b: usize) -> usize {
    a + b
}
const RESULT: usize = add(5, 10); // 编译期算出结果

const fn + const 泛型

rust 复制代码
struct Buffer<const N: usize> {
    data: [u8; N],
}
const fn size(f: usize) -> usize { f * 1024 }

fn main() {
    const S: usize = size(4);
    let buf = Buffer::<S> { data: [0; S] };
}

10. 泛型性能:零成本抽象

  • Rust 在编译期做单态化:为每种实际类型生成独立代码
  • 运行时无额外开销,效率等同于手写多份重复代码
  • 代价:编译稍慢、二进制体积稍大

示例:

rust 复制代码
let integer = Some(5);
let float = Some(5.0);

编译后会生成:

rust 复制代码
enum Option_i32 { Some(i32), None }
enum Option_f64 { Some(f64), None }

全文核心要点

  1. 泛型 = 通用代码模板,减少重复
  2. 泛型必须先声明再使用
  3. 必须用 Trait 约束类型行为(比较、加法等)
  4. 支持函数、结构体、枚举、方法泛型
  5. Rust 独有:const 泛型 (处理长度 / 常量)+ const fn(编译期计算)
  6. 零成本抽象,运行时无性能损失
相关推荐
小樱花的樱花2 小时前
Linux Shell命令入门
linux·服务器·开发语言
沫璃染墨2 小时前
C++ std::list 深度解析:迭代器、splice 核心接口与排序效率全解
开发语言·c++
没有天赋那就反复2 小时前
C++里面引用参数和实参的区别
开发语言·c++·算法
MinterFusion2 小时前
如何使用Qt5在窗口中显示矩形(v0.1.3)(下)
开发语言·qt·编程·明德融创·窗口中绘制矩形
misL NITL2 小时前
数据库操作与数据管理——Rust 与 SQLite 的集成
数据库·rust·sqlite
Mr.E52 小时前
odoo18 关闭搜索框点击自动弹出下拉框
开发语言·前端·javascript·odoo·owl·odoo18
星越华夏2 小时前
Pycharm运行正常,pyinstaller打包exe运行报错
ide·windows·pycharm
xyq20242 小时前
MongoDB GridFS
开发语言
TIEM_692 小时前
C++string接口(下)|修改器、字符串操作、成员常量、非成员函数重载
开发语言·c++