【Rust自学】5.1. 定义并实例化struct

喜欢的话别忘了点赞、收藏加关注哦,对接下来的教程有兴趣的可以关注专栏。谢谢喵!(=・ω・=)

5.1.1. 什么是struct

struct的中文意思为结构体,它是一种自定义的数据类型,它允许程序为相关联的值命名和打包,形成有意义的组合。它类似于其他编程语言中的“类”或“结构”,但它只提供数据存储功能,不包含方法。

学过C/C++的人可能对struct这个关键字很熟悉,但它们有区别:

  • C:struct 是一种用来组织数据的简单聚合类型。它只能包含数据,没有方法。

  • C++:struct 与 class 非常相似,可以包含数据和方法,唯一的语法区别是在 struct 中,默认的访问权限是 public;在 class 中,默认的访问权限是 private。

  • Rust:struct 仅用于定义数据结构,不包含方法,方法需要通过 impl 块为结构体定义。Rust 提供了更严格的所有权、生命周期和内存管理机制。

5.1.2. 定义struct

  • 使用struct这个关键字,为整个struct命名(驼峰命名法)
  • 在花括号内,为所有字段(Field) 定义 名称类型

例子:
为HLTV上的CS职业选手定制存储各项数据的struct(补充信息:CS职业选手的数据一般由Rating评分、DPR每回合死亡数、KAST不白给率、Impact影响力、ADR平均每回合伤害、KPR每回合击杀数组成)
请添加图片描述

struct Stats{  
    rating: f32,  
    dpr: f32,  
    kast: f32,  
    impact: f32,  
    adr: f32,  
    kpr: f32,  
}

5.1.3. 实例化struct

想要使用struct,需要创建struct的实例:

  • 为每个字段指定具体值,不能少赋字段的值
  • 无需按声明的顺序进行指定

就以donk为例创建他的数据库:

fn main() {  
    let donk = Stats {  
        rating: 1.27,  
        impact: 1.4,  
        dpr: 0.67,  
        adr: 88.8,  
        kast: 74.1,  
        kpr: 0.85,  
    };  
}

5.1.4. 取得struct里某个字段的值

使用点标记法可以取得struct里字段的值:

fn main() {  
    let mut donk = Stats {  
        rating: 1.27,  
        impact: 1.4,  
        dpr: 0.67,  
        adr: 88.8,  
        kast: 74.1,  
        kpr: 0.85,  
    };  
    donk.rating = 2.59;  
}

如果要更改struct的值,记得在实例化时使用可变变量关键字mut

在struct中,可变性的最小单位就是单个实例,不能控制单个字段的可变性。一旦struct实例被声明为可变的,那么这个实例下的所有字段都是可变的。

5.1.5. 使用struct作为函数返回值

函数里的最后一个表达式就是它的返回值,所以使用struct作为返回值就只需要确保构建struct是这个函数的最后一个表达式(不带分号)就行:

fn change_stats(rating: f32, impact:f32, dpr:f32, adr:f32, kast:f32, kpr:f32) -> Stats{  
    Stats {  
        rating: rating,  
        impact: impact,  
        dpr: dpr,  
        adr: adr,  
        kast: kast,  
        kpr: kpr,  
    }  
}

5.1.6. 字段初始化的简写

Rust与JS和C#一样在某些情况下它的字段初始化是可以简写的

当字段名与字段值对应变量名相同时,就可以简写。比如在上一个代码例中,所有的字段名都和字段值对应的变量名相同,所以可以将其简写为:

fn change_stats(rating: f32, impact:f32, dpr:f32, adr:f32, kast:f32, kpr:f32) -> Stats{  
    Stats {  
        rating,  
        impact,  
        dpr,  
        adr,  
        kast,  
        kpr,  
    }  
}

当然不只是全部对应才能这么写,只要有一个字段符合简写条件就可以,其他的保持正常写法就行。

5.1.7. struct的更新语法

当你基于某个struct实例来创建一个新的实例的时候,如果新实例的字段有与先前实例里的字段相同的,就可以使用更新语法。

比如我要给存储sh1ro的数据,他的rating是1.25,impact是1.2,其余与donk一样,这是基础的写法:

fn main() {  
    let donk = Stats {  
        rating: 1.27,  
        impact: 1.4,  
        dpr: 0.67,  
        adr: 88.8,  
        kast: 74.1,  
        kpr: 0.85,  
    };  
    let sh1ro = Stats {  
        rating: 1.25,  
        impact: 1.2,  
        dpr: donk.dpr,  
		adr: donk.adr,  
		kast: donk.kast,  
		kpr: donk.kpr,
    };  
}

这样写比较麻烦,所以Rust提供了这样的语法糖:

fn main() {  
    let donk = Stats {  
        rating: 1.27,  
        impact: 1.4,  
        dpr: 0.67,  
        adr: 88.8,  
        kast: 74.1,  
        kpr: 0.85,  
    };  
    let sh1ro = Stats {  
        rating: 1.25,  
        impact: 1.2,  
        ..donk  
    };  
}

只需要写有变化的部分,其余一样的部分只需要写..加上另一个struct实例的名字即可,表示剩下的没有赋值的字段的值都与另一个实例对应字段的值相同

5.1.8. 元组结构体Tuple struct

其中文名叫做元组结构体,指的是类似元组的结构体。元组结构体整体有名字,但里面的元素没有。适用于想给整个tuple起名,并让它不同于其他tuple,而且又不需要给每个元素起名。

定义tuple struct:使用struct关键字,后边是名字,以及里面元素的类型。

例子:

struct Color(u8, u8, u8);
struct Point(i32, i32, i32);
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);

有的人戏谑地说:tuple struct在传统编程语言没有类似物,这是来自Haskell的高贵血统。这是因为在许多传统的面向对象语言(如 Java、C++)中,结构体或类是具名且字段命名的,而元组则是匿名且仅基于顺序的。没有中间形式来融合两者的优点。Rust的 tuple struct 概念与Haskell的新类型(Newtype Pattern) 有直接关系,Haskell中可以通过newtype来定义类似的模式。

需要注意的是,即使两个元组结构体有相同数量的元素并且对应元素的数据类型都一样,它们也不该被称为相同的类型,因为它们是不同的struct。

5.1.9. 类单元结构体Unit-Like Struct

unit-like struct被称为类单元结构体,因为它们的行为类似于单元类型()。当需要类型标记或是在某种类型上实现trait(可以理解为接口)但不想要在类型本身中存储任何数据时。类似于Go语言中的interface{}

struct ReadOnly;
struct WriteOnly;

fn process_data<T>(_mode: T) {
    // 仅用于类型标记
}

fn main() {
    process_data(ReadOnly);
    process_data(WriteOnly);
}

这个例子实现了类型标记

5.1.10. struct数据的所有权

struct User { 
active: bool, 
username: String, 
email: String, 
sign_in_count: u64, 
}

在这个例子中,usernameemail都使用的是String类型而不是&str,因为String类型是自有类型(owned type),拥有自身全部数据的所有权。在这种情况下,只要它的实例是有效的,那么里面的字段数据也肯定是有效的。

&str这样的引用类型也可以存放进struct里,但这需要生命周期(以后讲)。在这里先简单地来说,生命周期保证只要struct实例是有效的,那么里面的引用也是有效的。如果struct里面存储引用,而不使用生命周期,就会报错(missing lifetime specifier)。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/941041.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【自动驾驶】单目摄像头实现自动驾驶3D目标检测

&#x1f351;个人主页&#xff1a;Jupiter. &#x1f680; 所属专栏&#xff1a;传知代码 欢迎大家点赞收藏评论&#x1f60a; 目录 概述算法介绍演示效果图像推理视频推理 核心代码算法处理过程使用方式环境搭建下载权重文件pytorch 推理&#xff08;自动选择CPU或GPU&#x…

Python+OpenCV系列:AI看图识人、识车、识万物

在人工智能风靡全球的今天&#xff0c;用 Python 和 OpenCV 结合机器学习实现物体识别&#xff0c;不仅是酷炫技能&#xff0c;更是掌握未来的敲门砖。本篇博文手把手教你如何通过摄像头或图片输入&#xff0c;识别人、动物、车辆及其他物品&#xff0c;让你的程序瞬间具备 AI …

永磁同步电机负载估计算法--自适应扩张状态观测器

一、 原理介绍 在线性扩张观测器中&#xff0c;LESO观测器增益ω0 决定了观测器的跟踪速度&#xff0c;ω0 越大&#xff0c;观测器估计精度越高&#xff0c; 抗干扰能力越强&#xff0c;瞬态响应速度加快&#xff0c;过大则会引入高频噪声使系统不稳定。为使观测器在全速域内…

【Spring事务】深入浅出Spring事务从原理到源码

什么是事务 保证业务操作完整性的一种数据库机制 &#xff08;driver 驱动&#xff09;事务特定 ACID A 原子性 &#xff08;多次操作 要不一起成功 要不一起失败 &#xff08;部分失败 savepoint&#xff09;&#xff09; C 一致性 &#xff08;事务开始时数据状态&#xff0c…

Apache解析漏洞(apache_parsingCVE-2017-15715)

apache_parsing 到浏览器中访问网站 http://8.155.8.239:81/ 我们写一个木马 1.php.jpg 我们将写好的木马上传 会得到我们上传文件的路径 我们访问一下 发现上传成功 发现木马运行成功&#xff0c;接下来使用蚁剑连接我们的图片马 获取 shell 成功 CVE-2013-454 我们还是到…

CCF-GESP 等级考试 2023年9月认证C++二级真题解析

2023年9月真题 一、单选题&#xff08;每题2分&#xff0c;共30分&#xff09; 正确答案&#xff1a;D 解析&#xff1a;考察知识点&#xff1a;计算机基础 本题属于考察计算机基础知识。中国第一台计算机通用数字电子计算机于 1958 年 6 月由中科院计算所研制成功。那时候的逻…

linux环境使用yum方式安装nginx

linux环境使用yum方式安装nginx 一、nginx官网 二、nginx安装 点击首页的 Docs 或者 install 都可以&#xff0c;最终都是进入到Installing nginx页面 因为安装的服务器环境是linux centos 所以选择 Installation on Linux下面 packages 跳转链接 点击packages后 最终会跳转…

CS 144 check6: buiding an IP router

Lecture Notes Exercises 路由器的任务是根据路由表转发接收到的数据报&#xff1a;路由表是一系列规则&#xff0c;用于指导路由器针对任何给定的数据报应如何进行转发。 发送出什么接口。下一跳的IP地址。 这个check的工作是实现一个路由器&#xff0c;它可以为任何给定的…

Android Studio IDE环境配置

​需要安装哪些东西&#xff1a; Java jdk Java Downloads | OracleAndroid Studio 下载 Android Studio 和应用工具 - Android 开发者 | Android DevelopersAndroid Sdk 现在的Android Studio版本安装时会自动安装&#xff0c;需要注意下安装的路径Android Studio插件…

时钟周期、机器周期及指令周期是什么关系?

组成原理中&#xff0c;时钟周期、机器周期和指令周期是三个至关重要的概念&#xff0c;它们共同定义了计算机执行指令的基本时间框架。本文将对这三个周期进行详细介绍&#xff0c;并展示它们的工作原理。 一、时钟周期&#xff08;Clock Cycle&#xff09; 定义与作用 主…

YOLOv8改进,YOLOv8引入Hyper-YOLO的MANet混合聚合网络+HyperC2Net网络

摘要 理论介绍 MANet 的目标是通过多种卷积操作的协同作用,提高特征提取能力,并加强梯度流动,从而提升模型在不同层次的特征表示和语义深度。MANet 结合了三种卷积变体,通过混合使用它们来提高视觉特征的多样性和信息流动性。 HyperC2Net 的主要目标是通过超图结构对多层次…

挑战一个月基本掌握C++(第六天)了解函数,数字,数组,字符串

一 C函数 函数是一组一起执行一个任务的语句。每个 C 程序都至少有一个函数&#xff0c;即主函数 main() &#xff0c;所有简单的程序都可以定义其他额外的函数。 您可以把代码划分到不同的函数中。如何划分代码到不同的函数中是由您来决定的&#xff0c;但在逻辑上&#xff…

vue的ElMessage的css样式不生效

我使用elementplus&#xff0c;是使用的用哪个单独引入的&#xff0c;然后表单校验时候警告的css不生效&#xff0c;就是这个效果 反复看视频的引入也没发现问题&#xff0c;后来才知道需要这个引入 import { ElMessage } from "element-plus"; import element-pl…

PromptGIP:Unifying lmage Processing as Visual Prompting Question Answering

“Unifying Image Processing as Visual Prompting Question Answering” 文章提出了一种名为 PromptGIP 的通用模型&#xff0c;将图像处理任务统一为视觉提示问答范式&#xff0c;在多个图像处理任务上展现出良好性能&#xff0c;为通用图像处理提供了新的思路和方法。 confe…

Windows服务器修复SSL/TLS协议信息泄露漏洞等...

为了保证生产环境的安全, 我们会定期对服务器进行漏洞扫描, 一般情况下我们都是使用Linux服务器, 某些情况会用到Windows服务器 出现SSL/TLS协议信息泄露漏洞问题一般情况下是远程连接使用了不安全的加密算法, 需要禁用这些加密算法 修复方法 从网络中查询修复方法又很多, 大…

基于AT89C52单片机的6位电子密码锁设计

点击链接获取Keil源码与Project Backups仿真图&#xff1a; https://download.csdn.net/download/qq_64505944/90166684?spm1001.2014.3001.5503 14 部分参考设计如下&#xff1a; 目 录 摘要 1 abstract 2 1 绪论 3 1.1 课题背景 3 1.2 课题的目的和意义 3 1.3 电子密码…

考前倒计时98天

2024年12月21日到2025年3月29日共有 98​ 天 一、计算机基础 思维分类特征强调学科代表理论思维&#xff08;推理思维&#xff09;推理和演绎推理数学实验思维&#xff08;证实思维&#xff09;观察和总结自然规律归纳物理学计算思维&#xff08;构造思维&#xff09;设计和构造…

力扣-图论-70【算法学习day.70】

前言 ###我做这类文章一个重要的目的还是给正在学习的大家提供方向和记录学习过程&#xff08;例如想要掌握基础用法&#xff0c;该刷哪些题&#xff1f;&#xff09;我的解析也不会做的非常详细&#xff0c;只会提供思路和一些关键点&#xff0c;力扣上的大佬们的题解质量是非…

最新详细Gmail 注册指南以及注册谷歌账号手机号码无法验证?解决方法分享

Gmail 注册指南&#xff1a;2024 年实用教程&#xff0c;解决手机号验证难题&#xff0c;开启你的数字之旅 在当今信息时代&#xff0c;Gmail 邮箱已成为我们工作与生活中常用的数字工具&#xff0c;它不仅功能强大、界面简洁&#xff0c;还是访问 Google 服务&#xff08;如 …

【已解决】黑马点评项目jmeter高并发测试中用户数据的生成

具体实现见此篇文章的第3章 运行 test 程序后&#xff0c;生成以下用户名 以下文件名改成自己的地址 成功