结构体定义中的泛型类型参数并不总是与结构体方法签名中使用的泛型是同一类型 。看下面的代码:
struct Point<X1, Y1> {x: X1,y: Y1,}impl<X1, Y1> Point<X1, Y1> {fn mixup<X2, Y2>(self, other: Point<X2, Y2>) -> Point<X1, Y2> {Point {x: self.x,y: other.y,}}}fn main() {let p1 = Point { x: 5, y: 10.4 };let p2 = Point { x: "Hello", y: 'c' };let p3 = p1.mixup(p2);println!("p3.x = {}, p3.y = {}", p3.x, p3.y);}
在上面的代码中, Point 结构体使用了泛型类型 X1 和 Y1,为 mixup 方法签名使用了 X2 和 Y2 来使得示例更加清楚 。这个方法用 self 的 Point 类型的 x 值(类型 X1)和参数的 Point 类型的 y 值(类型 Y2)来创建一个新 Point 类型的实例
在 main 函数中,定义了一个有 i32 类型的 x(其值为 5)和 f64 的 y(其值为 10.4)的 Point 。p2 则是一个有着字符串 slice 类型的 x(其值为 "Hello")和 char 类型的 y(其值为c)的 Point 。在 p1 上以 p2 作为参数调用 mixup 会返回一个 p3,它会有一个 i32 类型的 x,因为 x 来自 p1,并拥有一个 char 类型的 y , 因为 y 来自 p2 。println! 会打印出 p3.x = 5, p3.y = c 。
这个例子的目的是展示一些泛型通过 impl 声明而另一些通过方法定义声明的情况 。这里泛型参数 X1 和 Y1 声明于 impl 之后 , 因为它们与结构体定义相对应 。而泛型参数 X2 和 Y2 声明于 fn mixup 之后,因为它们只是相对于方法本身的 。
6.泛型代码性能不用担心使用泛型会比使用具体类型的代码性能低 。
Rust 通过在编译时进行泛型代码的 单态化(monomorphization)来保证效率 。单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程 。
在这个过程中,编译器寻找所有泛型代码被调用的位置并使用泛型代码针对具体类型生成代码 。
下面看看这个怎样用于标准库中的 Option 枚举:
let integer = Some(5);let float = Some(5.0);
当 Rust 编译这些代码的时候 , 它会进行单态化 。编译器会读取传递给 Option<T> 的值并发现有两种 Option<T>:一个对应 i32 另一个对应 f64 。为此,它会将泛型定义 Option<T> 展开为两个针对 i32 和 f64 的定义,接着将泛型定义替换为这两个具体的定义 。
编译器生成的单态化版本的代码看起来像这样(编译器会使用不同于如下假想的名字):
enum Option_i32 {Some(i32),None,}enum Option_f64 {Some(f64),None,}fn main() {let integer = Option_i32::Some(5);let float = Option_f64::Some(5.0);}
泛型 Option<T> 被编译器替换为了具体的定义 。因为 Rust 会将每种情况下的泛型代码编译为具体类型 , 使用泛型没有运行时开销 。当代码运行时,它的执行效率就跟好像手写每个具体定义的重复代码一样 。这个单态化过程正是 Rust 泛型在运行时极其高效的原因 。
推荐阅读
- 指针变量在C/C++中的内存占用
- 什么是Rust语言 ,特点是什么,跟其它语言对比有什么优势
- Go编程中调用外部命令的几种场景
- 搜索引擎友好型特点结构清晰、解决用户问题、内容更新快
- WPS卡住了,怎么办?
- 在 Rust 编程中使用多线程
- 只有了解关键词排名机制,才可以避免走入网站优化深渊
- 秀米该咋滴才可以上传视频,如何在秀米编辑器中上传图片
- 在哪里开失业证明?
- 男性器官衰老顺序已公开,建议对照一下,看看自己在哪个阶段?