Rust之泛型、特性和生命期(一):通用数据类型

rust笔记12:rust的泛型 Rust 的泛型实现是其类型系统的核心特性之一,它允许编写灵活且可重用的代码,同时保持类型安全和性能。以下从 泛型数据类型、泛型类型参数、trait bound 和 生命周期泛型 四个方面详细介绍 Rust 的泛型实现,并解释编译器如何通过 静态分发 处理泛型。 阅读详情

开发环境 

  • Windows 10
  • Rust 1.69.0

 

  • VS Code 1.78.2

  项目工程

这里继续沿用上次工程rust-demo

通用数据类型

 我们使用泛型来为函数签名或结构等项目创建定义,然后我们可以将其用于许多不同的具体数据类型。让我们首先看看如何使用泛型来定义函数、结构、枚举和方法。然后我们将讨论泛型如何影响代码性能。 

函数的泛型定义

当定义一个使用泛型的函数时,我们将泛型放在函数的签名中,在这里我们通常会指定参数和返回值的数据类型。这样做使我们的代码更加灵活,为我们的函数的调用者提供更多的功能,同时防止代码重复。

继续我们的最大函数,示例4显示了两个函数,它们都能找到一个片断中的最大值。然后我们将把它们合并成一个使用泛型的函数。

文件名:src/main.rs

fn largest_i32(list: &[i32]) -> &i32 {         // largest_i32 函数
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn largest_char(list: &[char]) -> &char {      // largest_char 函数
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn main() {
    let number_list = vec![34, 50, 25, 100, 65];

    let result = largest_i32(&number_list);
    println!("The largest number is {}", result);

    let char_list = vec!['y', 'm', 'a', 'q'];

    let result = largest_char(&char_list);
    println!("The largest char is {}", result);
}

示例4:两个函数只在名称和签名中的类型上有所不同

largest_i32函数就是我们在上一节示例3中提取的那个函数,它可以找到一个片断中最大的i32。biggest_char函数找到一个片断中最大的char。这些函数体有相同的代码,所以让我们通过在一个函数中引入一个通用类型参数来消除重复。 

为了在一个新的单一函数中对类型进行参数化,我们需要对类型参数进行命名,就像我们对函数的值参数所做的那样。你可以使用任何标识符作为类型参数名。但是我们将使用T,因为按照惯例,Rust中的类型参数名很短,通常只有一个字母,而且Rust的类型命名惯例是UpperCamelCase(驼峰命名法)。T是 "类型 "的简称,是大多数Rust程序员的默认选择。

当我们在函数主体中使用参数时,我们必须在签名中声明参数名称,以便编译器知道这个名称的含义。同样地,当我们在函数签名中使用一个类型参数名时,我们必须在使用它之前声明类型参数名。为了定义通用的largest,将类型名称声明放在角括号内,<>,在函数名称和参数列表之间,像这样:

fn largest<T>(list: &[T]) -> &T {

我们把这个定义理解为:函数largest在某种类型T上是通用的。这个函数有一个名为list的参数,它是一个类型为T的值的切片。largest将返回一个对同一类型T的值的引用。

示例5显示了在其签名中使用通用数据类型的组合largest定义。该清单还显示了我们如何用i32值的切片或char值调用该函数。注意,这段代码还不能编译,但我们将在本章后面修复它。 

文件名: src/main.rs

fn largest<T>(list: &[T]) -> &T {       // largest函数的泛型定义
    let mut largest = &list[0];

    for item in list {
        if item > largest {
            largest = item;
        }
    }

    largest
}

fn main() {
    let number_list = vec![34, 50, 25, 100, 65];

    let result = largest(&number_list);                // 调用largest函数
    println!("The largest number is {}", result);

    let char_list = vec!['y', 'm', 'a', 'q'];

    let result = largest(&char_list);
    println!("The largest char is {}", result);
}

 示例5:使用通用类型参数的largest,这还不能编译

编译

cargo run

 帮助信息提到了std::cmp::PartialOrd,它是一个trait,我们将在下一节讨论trait。现在,我们要知道,这个错误说明,largest对所有可能的T的类型都不起作用。因为我们想在主体中比较类型T的值,我们只能使用值可以被排序的类型。为了实现比较,标准库有std::cmp::PartialOrd特质,你可以在类型上实现它(关于这个特质的更多信息,见附录C)。按照帮助信息的建议,我们把对T有效的类型限制为只实现PartialOrd的类型,这个例子就可以编译了,因为标准库对i32和char都实现了PartialOrd。

结构体的泛型定义

我们还可以使用<>语法定义结构,在一个或多个字段中使用通用类型参数。示例6 定义了一个 Point<T> 结构来保存任何类型的 x 和 y 坐标值。

文件名: src/main.rs

struct Point<T> {             // 结构体的泛型定义
    x: T,
    y: T,
}

fn main() {
    let integer = Point { x: 5, y: 10 };
    let float = Point { x: 1.0, y: 4.0 };
}

示例6:一个带有T类型的x和y值的Point<T>结构

在结构体定义中使用泛型的语法与函数定义中使用的语法类似。首先,我们在结构名称之后的角括号内声明类型参数的名称。然后,我们在结构定义中使用泛型,否则我们会指定具体的数据类型。 

注意,因为我们只用了一个泛型来定义Point<T>,这个定义说Point<T>结构是某个类型T的泛型,字段x和y都是同一类型,不管这个类型是什么。如果我们创建一个具有不同类型值的 Point<T> 实例,如示例7 所示,我们的代码将无法编译。

文件名:src/main.rs

struct Point<T> {
    x: T,
    y: T,
}

fn main() {
    let wont_work = Point { x: 5, y: 4.0 };
}

示例7: 字段x和y必须是相同的类型,因为两者有相同的通用数据类型T

编译

cargo run

 在这个例子中,当我们把整数值5分配给x时,我们让编译器知道,对于Point<T>的这个实例,通用类型T将是一个整数。然后,当我们为y指定4.0时,我们已经定义了与x相同的类型,我们会得到一个类型不匹配的错误,像这样: 

为了定义一个x和y都是泛型但可能有不同类型的Point结构,我们可以使用多个泛型参数。例如,在示例8中,我们将Point的定义改为T和U类型的泛型,其中x是T类型的,y是U类型的。

struct Point<T, U> {         // 两种数据类型的结构体泛型定义
    x: T,
    y: U,
}

fn main() {
    let both_integer = Point { x: 5, y: 10 };
    let both_float = Point { x: 1.0, y: 4.0 };
    let integer_and_float = Point { x: 5, y: 4.0 };
    
    println!("both_integer.x = {}, both_integer.y= {}", both_integer.x, both_integer.y);
    println!("both_float.x = {}, both_float.x = {}", both_float.x, both_float.y);
    println!("integer_and_float.x = {}, integer_and_float.y = {}", integer_and_float.x, integer_and_float.y);
}

示例8:一个Point<T, U>在两种类型上的泛型,以便x和y可以是不同类型的值

编译

 

 现在,所有显示的Point的实例都被允许了! 你可以在一个定义中使用尽可能多的泛型参数,但使用多了会使你的代码难以阅读。如果你发现你的代码中需要大量的泛型,这可能表明你的代码需要重组成小块。

枚举的泛型定义

就像我们对结构体所做的那样,我们可以定义枚举来保存其变体中的通用数据类型。让我们再看看标准库提供的Option<T>枚举,我们在之前的章节中使用过它:

enum Option<T> {
    Some(T),
    None,
}

这个定义现在对你来说应该更有意义了。正如你所看到的,Option<T>枚举对T类型是通用的,有两个变体: Some,它持有一个T类型的值,和一个None变体,它不持有任何值。通过使用Option<T>枚举,我们可以表达一个可选值的抽象概念,由于Option<T>是通用的,所以无论可选值的类型是什么,我们都可以使用这个抽象概念。

枚举也可以使用多个通用类型。我们在之前章节种使用的Result枚举的定义就是一个例子: 

enum Result<T, E> {
    Ok(T),
    Err(E),
}

 Result枚举在两种类型上是通用的,即T和E,并且有两个变量:Ok, 持有一个T类型的值,Err,它持有一个E类型的值。这个定义使得我们可以在任何有可能成功(返回某种类型的T的值)或失败(返回某种类型的E的错误)的操作中使用Result枚举。事实上,这就是我们在之前章节的示例中用来打开一个文件的方法,当文件被成功打开时,T被填写为std::fs::File类型,当打开文件有问题时,E被填写为std::io::Error类型。

当你发现你的代码中有多个结构或枚举的定义,而这些定义只在它们持有的值的类型上有区别时,你可以通过使用通用类型来避免重复的情况。

方法的泛型定义

我们可以在结构体和枚举上实现方法(就像我们在之前章中做的那样),也可以在它们的定义中使用通用类型。示例9显示了我们在清示例6中定义的Point<T>结构,并在其上实现了一个名为x的方法。

文件名: src/main.rs

struct Point<T> {
    x: T,
    y: T,
}

impl<T> Point<T> {              // 方法的泛型定义
    fn x(&self) -> &T {
        &self.x
    }
}

fn main() {
    let p = Point { x: 5, y: 10 };

    println!("p.x = {}", p.x());
}

示例9:在Point<T>结构上实现一个名为x的方法,该方法将返回一个对T类型的x字段的引用

编译

这里,我们在Point<T>上定义了一个名为x的方法,返回对字段x中数据的引用。 

请注意,我们必须在impl之后声明T,这样我们就可以用T来指定我们在Point<T><T>这个类型上实现方法。通过在 impl之后将T声明为泛型,Rust 可以确定 Point 中角括号中的类型是一个泛型,而不是一个具体类型。我们可以为这个泛型参数选择一个与结构定义中声明的泛型参数不同的名字,但使用相同的名字是常规的。在声明了泛型的impl函数中编写的方法将被定义在该类型的任何实例上,无论最终用什么具体类型来替代泛型。 

在定义类型上的方法时,我们也可以指定对泛型的约束。例如,我们可以只在 Point<f32> 实例上实现方法,而不是在具有任何泛型的 Point<T> 实例上。在示例10中,我们使用了具体的类型f32,这意味着我们没有在impl后面声明任何类型。

文件名: src/main.rs

impl Point<f32> {
    fn distance_from_origin(&self) -> f32 {
        (self.x.powi(2) + self.y.powi(2)).sqrt()
    }
}

示例10:一个impl块,它只适用于具有特定具体类型的通用类型参数T的结构

这段代码意味着Point<f32>类型将有一个distance_from_origin方法;其他Point<T>的实例,如果T不属于f32类型,则不会定义这个方法。该方法测量我们的点离坐标(0.0, 0.0)处的点有多远,并使用仅对浮点类型可用的数学运算。 

结构定义中的通用类型参数并不总是与你在同一结构的方法签名中使用的参数相同。示例11在Point结构中使用了通用类型X1和Y1,在mixup方法签名中使用了X2 Y2,以使例子更加清晰。该方法创建了一个新的Point实例,其X值来自于自身的Point(类型为X1),Y值来自于传入的Point(类型为Y2)。

文件名: src/main.rs

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);
}

示例11:一个使用不同于其结构定义的通用类型的方法

编译

 在main中,我们定义了一个Point,其中i32为x(值为5),f64为y(值为10.4)。p2变量是一个Point结构,其中x是一个字符串片(值为 "Hello"),y是一个char(值为c)。在p1上调用mixup,参数为p2,得到p3,它有一个i32的x,因为x来自p1。p3变量将有一个char作为y,因为y来自p2。println!宏调用将打印p3.x = 5, p3.y = c。 

这个例子的目的是演示这样一种情况:一些泛型参数与 impl 一起声明,一些则与方法定义一起声明。在这里,泛型参数X1和Y1是在impl之后声明的,因为它们与结构定义一起。泛型参数X2和Y2是在fn mixup之后声明的,因为它们只与方法相关。 

使用泛型的代码的性能

你可能想知道在使用通用类型参数时是否有运行时间成本。好消息是,使用泛型不会使你的程序比使用具体类型的程序运行得更慢。

Rust通过在编译时对使用泛型的代码进行单态化来实现这一点。单态化是指通过填写编译时使用的具体类型,将泛型代码变成具体代码的过程。在这个过程中,编译器所做的与我们在示例5中创建泛型函数的步骤相反:编译器会查看所有调用泛型代码的地方,并为泛型代码所调用的具体类型生成代码。

 让我们通过使用标准库的通用Option<T>枚举来看看这是如何工作的:

let integer = Some(5);
let float = Some(5.0);

当Rust编译这段代码时,它进行了单态化。在这个过程中,编译器读取了Option<T>实例中使用的值,并确定了两种Option<T>:一种是i32,另一种是f64。因此,它将Option<T>的通用定义扩展为两个专门针对i32和f64的定义,从而用特定的定义代替了通用定义。

代码的单态化版本看起来与下面类似(编译器使用的名称与我们在这里使用的不同,以示说明):

文件名: src/main.rs 

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的泛型在运行时非常高效。

本章重点

  • 通用数据类型分类
  • 函数的泛型定义
  • 结构体的泛型定义
  • 枚举的泛型定义
  • 方法的泛型定义
FLTK自定义拖拽控件实现窗口分割 本文主要介绍了在FLTK中如何自定义一个窗口分割控件,实现窗口的布局,该控件可以实现拖拉窗口和隐藏侧边栏功能。 立即下载

相关推荐

STM32实战:ADXL345传感器驱动与数据采集全解析(IIC/SPI双模式适配)

本文详细解析了STM32驱动ADXL345传感器的全流程,包括IIC和SPI双模式适配、硬件连接、寄存器配置及数据采集处理。通过实战代码示例和常见问题排查指南,帮助开发者快速实现高精度加速度数据采集,适用于运动检测、姿态识别等多种嵌入式应用场景。

weixin_29171087的博客 313

Rust的泛型

文章目录Rust的泛型在函数中使用泛型特性与特性绑定在结构体中使用泛型 Rust的泛型 在函数中使用泛型 项目经理总是善变的,有一天项目经理告诉我,替客户计算一个圆形的面积。客户要求很简单,半径只会是u8类型。好,我写了如下代码: fn area_u8(r: u8) -> u8 { r * r } fn main() { println!("{}", area_u8(3)); } 可第二天项目经理又来了,说客户说的不对,半径某种情况下还会是u16。唉,客户就是上帝,项目经理也没有办

鸿鹄之志 4209

深入解析BLheli电调固件与Dshot通讯协议:从原理到实践

本文深入解析了无人机动力系统的核心——BLheli电调固件与Dshot通讯协议。详细阐述了BLheli固件从经典版到BLheli_32的演进及其功能特性,并重点剖析了Dshot数字协议如何通过数据包和校验码实现更快、更准、更可靠的电机控制。文章还涵盖了双向Dshot遥测、实战配置与调参指南,帮助玩家充分释放无人机性能。

weixin_28273593的博客 434

Rust学习:10.1_泛型和特征之泛型

为了学习Rust,阅读了github上的Rust By Practice电子书,本文章只是用来记录自己的学习过程,感兴趣的可以阅读[原书](https://zh.practice.rs/why-exercise.html),希望大家都能掌握Rust!

cacique111的博客 836

RTC 实时时钟实验

如果在 RTC_CR 寄存器中设置了相应的允许位,则在每个TR_CLK 周期中 RTC 产生一个中断(秒中断)。void BKP_WriteBackupRegister(uint16_t BKP_DR, uint16_t Data) // 往备份区域写用户数据的函数 (这个函数的第一个参数就是寄存器的标号了,这个是通过宏定义定义的)存储在 RTC_ALR 寄存器中的可编程时间相比较,如果 RTC_CR 控制寄存器中设置了相应允许位,比较匹配时将产生一个闹钟中断。寄存器操作完成,并同步之后,设置秒钟中断。

m0_55996456的博客 1205

告别环境配置噩梦:用Docker Desktop + WSL2在Windows上5分钟搞定vLLM运行环境

本文详细介绍了如何在Windows系统上使用Docker Desktop和WSL2快速搭建vLLM开发环境,5分钟内完成配置。通过容器化技术解决传统环境配置中的依赖冲突、环境污染等问题,提供一键复用的高效方案,特别适合AI开发者快速部署和测试vLLM框架。

weixin_28728495的博客 502

Rust 中的泛型

数据类型是对同一类数据的抽象,而泛型是对具有一组相同行为的数据类型的抽象。Rust 使用 trait 来描述这一组相同的行为,简单的说 trait 就是一组函数的集合。Rust中的trait类似于其他语言中的常被称为接口(interfaces)的功能。 泛型 在函数中使用泛型 假如有两个函数,它们的功能是查找slice中最大值并返回,函数体中的采用的算法是一样的,主要不同的是参数类型。如下所示: fn largest_i32(list: &[i32]) -> i32 { let mut

花落花开的博客 1420

十、强势股的起爆点:第三类买点的实战精解

本文深入解析强势股交易中的第三类买点(三买)实战技巧,涵盖两种经典模式:突破首个中枢后的回踩和底部反转后的直接脱离下跌中枢。通过详细案例和数据分析,揭示三买在捕捉主升浪起爆点时的黄金信号作用,帮助投资者优化风险收益比,提升短线交易成功率。

weixin_30260191的博客 310

rust 泛型、多态

无论是c++ STL还是rust std,里面所有的数据结构都是泛型的,c++和rust的结构体也类似,可以是泛型的也可以是非泛型的。所以,泛型函数内部对T的约束条件,都通过指明T所包含的trait的方式进行说明。Ord特征中并没有eq函数,但是Ord特征间接继承了PartialOrd,所以有Ord特征的类型肯定是可以使用==的。对于绝大部分trait,模板类型都是默认不包含该trait的,需要特征约束才能说明该类型具有该trait。作为泛型参数的常数类型,可以是所有整数类型、bool类型、char类型。

nameofcsdn的博客 2347

30、优化算法在芯片布局与药物设计中的应用

本文探讨了优化算法在芯片布局与药物设计中的关键应用。针对芯片布局问题,提出了一种改进的粒子群优化(PSO)方法,通过引入转向因子、重叠检测与消除机制以及优先处理约束模块,有效优化了芯片面积、线长和运行时间,并在有无布局约束条件下均优于传统方法。在药物设计领域,介绍了基于蚁群优化(ACO)的PLANTS算法,用于解决蛋白质-配体对接问题,通过离散化连续变量、信息素更新、局部搜索和聚类处理,提高了构象预测的准确性。文章还总结了两种算法的操作流程,并展望了未来在多约束集成与算法融合方向的发展潜力。

egg99的博客 94

Agentic AI为教育行业赋能,提示工程架构师解析应用潜力

然而,即便是最先进的 LLMs,在面对复杂、动态、需要持续规划和调整的教育场景时,也常常显得力不从心,它们更像是强大的“问答机器”,而非真正意义上的“学习伙伴”或“教学助手”。在教育场景中,传统的 AI 工具可能只能回答学生提出的特定问题,或者根据预设的规则推送一些学习材料。无论您是教育技术领域的开发者、产品经理,还是一线的教育工作者、教育管理者,抑或是对 AI 教育应用充满好奇的研究者,本文都将为您提供宝贵的 insights,助您把握 Agentic AI 时代教育创新的脉搏。

架构师的AI之路,分享AI应用开发架构的学习与实践。 466

rust泛型

RHS=Self,Self就是泛型参数默认值,它表示实现Add的类型,在这里就是Point类型。如果实现Add时不指定RHS的具体类型,RHS的类型将是Self类型。方法mixup将一个Point点的x与Point点的y融合成一个类型为Point的新点。单态化是一个通过填充编译时使用的具体类型,将通用代码转换为特定代码的过程。在编译期,会根据指定的具体类型,生成一套特化代码,这叫单态化。展开为两个针对i32和f64的定义,接着将泛型定义替换为这两个具体的定义。

void的博客 1557

WPF数据绑定Binding对数据的转换与效验(四)

Binding的作用就是架在Source与Target之间的桥梁,数据可以在这座桥梁的帮助下来流通。就像现实世界中的桥梁会设置一些关卡进行安检一样,Binding这座桥上也可以设置关卡对数据的有效性进行检验,不仅如此,当Binding的两端要求使用不同的数据类型时,我们还可以为数据设置转换器。Binding用于数据有效性检验的关卡是它的ValidationRules属性,用于数据类型转换的关卡是它的Converter属性。

qq_30725967的博客 1627

Rust基本类型

Rust 基本类型见下表,后面分节介绍。表2-1 Rust类型。

weixin_43219667的博客 994

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

Rust 编程语言入门指南:从零开始掌握系统级开发

在当今的编程语言生态中,Rust 以其独特的设计理念和卓越的性能表现,迅速成为系统级开发领域的一颗耀眼新星。它由 Mozilla 研究院于 2010 年首次发布,旨在提供 C++ 级别的性能,同时消除内存安全漏洞和数据竞争等常见问题。对于希望涉足系统编程、网络服务、嵌入式开发甚至 WebAssembly 的开发者而言,学习 Rust 无疑是一项极具价值的投资。本文将引导你踏上 Rust 的学习之旅,从环境搭建到核心概念理解,帮助你构建坚实的知识基础。开始 Rust 编程的第一步是配置开发环境。

2504_90294050的博客 697

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Rust (4.范型、特型、生命周期)

提前对范型的类型参数做约束,是很有必要的。在一些场景中,需要对范型进行一些约束。特型中有一堆还没实现的方法。特型和类型之间产生联系。

weixin_41043435的博客 344

Probability and Statistics - 4th edition

Probability and Statistics - 4th edition

Rust : 泛型与trait限定

先看代码: trait R{ } //#[derive(Clone)] // 加上会编译错误 struct P{ f:Vec<Box<dyn R>> } #[derive(Clone)] //可以加 struct Q<T> where T: R{ f: Vec<Box<T>> } fn main(){ } 在上面代码中,P和 Q有什么区别? Vec<Box< dyn R>>: 是可以装实现R特性的不同t

代码过客 1290

RUST 每日一省:泛型

泛型类型的结构体是指结构体的字段类型是泛型类型,它可以拥有一个或多个泛型类型。定义泛型结构体时,可以在结构体名称后面带上或等,在定义字段的类型时使用T或U。在implfor{}这个语法结构中, 泛型类型既可以出现在位置, 也可以出现在位置。函数的参数和返回值都可以是泛型类型,带有泛型类型的参数或返回值的函数叫作泛型函数。比如,Vec在使用中可以指定T的类型为i32或String等——Vec或者Vec。

The future is already here it's just not evenly distributed。 561

Rust:泛型

泛型单态化没有运行时开销 文章目录1、泛型数据结构枚举泛型结构体泛型泛型结构体定义泛型结构体方法2、trait什么是trait默认traittrait作为参数 1、泛型数据结构 枚举泛型 enum Option&amp;lt;T&amp;gt; { Some(T), None, } 结构体泛型 泛型结构体定义 struct Point&amp;lt;T&amp;gt;{ x:T, y:T, ...

OceanStar的博客 1856

Rust语言从入门到入坑——(8)Rust泛型与特性

泛型是一个编程语言不可或缺的机制。

记录一些平时工作或者学习中的瞬间 1073

Rust 学习笔记:泛型

Rust 学习笔记:泛型

ProgramNovice的博客 1242

[rust]泛型比大小

泛型数据进行比较

hide_in_darkness的博客 345

Rust学习记录 -> 泛型使用:结构体方法,引用和特性

文章目录前言一、问题简述二、改进过程1.使用不可变引用2.声明泛型特性总结 前言 本文就笔者在学习rust泛型使用时遇到的一个问题进行剖析并给出解决办法 提示:以下是本篇文章正文内容,下面案例可供参考 一、问题简述 首先建立如下包含两个未声明特性的结构体,代码如下: struct str2<T,E> { x:T, y:E, } 再对其声明包含的方法: impl<T,E> str2<T,E> { fn get_x(&self) -&gt

weixin_45704680的博客 1006

Rust 深度解析:泛型 —— “零成本”的抽象艺术

当你写并用i32调用它时,Rust 编译器(在编译时)会为你自动生成一个版本:当你用f64调用它时,编译器会自动生成版本。这个过程叫做单态化 (Monomorphization)。这意味着什么?你(开发者)得到了抽象的便利(只写一个largest<T>而最终的用户(运行程序时)得到了具体的性能(程序运行的就是,没有动态类型检查,没有虚函数表查询,没有运行时开销)。这就是 Rust 的**“零成本抽象”**。泛型是 Rust 在不牺牲性能的前提下实现惊人安全性和表达力的基石。

2403_88996352的博客 664

Rust泛型与trait特性,模仿接口的实现

泛型是一个编程语言不可或缺的机制。C++ 语言中用"模板"来实现泛型,而 C 语言中没有泛型的机制,这也导致 C 语言难以构建类型复杂的工程。泛型机制是编程语言用于表达类型抽象的机制,一般用于功能确定、数据类型待定的类,如链表、映射表等。这是一个对整型数字选择排序的方法: 运行结果: 这是一个简单的取最大值程序,可以用于处理 i32 数字类型的数据,但无法用于 f64 类型的数据。通过使用泛型我们可以使这个函数可以利用到各个类型中去。但实际上并不是所有的数据类型都可以比大小,所以接下来一段代码并不是

1292

【Rust 基础篇】Rust 中的泛型:结构体和方法

本篇博客详细介绍了在 Rust 的结构体和方法中使用泛型的方法。通过泛型,我们可以编写通用的代码,提高代码的复用性和灵活性。希望本篇博客对你理解和应用 Rust 中的泛型有所帮助。

繁依Fanyi的博客 1075
上一篇: Rust之泛型、特性和生命期(一):基本概念
下一篇: Rust之泛型、特性和生命期(二):Traits:定义共同的行为
枫★曦
博客等级 码龄19年 251粉丝 153原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值