结构体

// 如何定义结构体
struct User {
active: bool,
username: String,
email: String,
sign_in_count: u64,
}
// 如何使用结构体
let user = User {
active: true,
username: String::from("someusername123"),
email: String::from("someone@example.com"),
sign_in_count: 1,
}
// 解构
// 这里有个需要注意的是,如果某个类型没有实现Copy trait
// 那么就会传递所有权,比如这里的email,所以在定义完user2以后,user变量就不能再使用了
// 如果我们额外传入了email,那么user就还能使用
// 另一个问题:结构的位置会影响最后的值吗?就像js的对象结构,我们可以在下面覆盖掉上面解构对象的某些属性
// 在Rust中,结构(destructuring)不是用来“覆盖”值的,而是用来“重组”已存在的值到一个新的变量。这跟JavaScript的对象解构赋值不同,后者允许你在解构的同时覆盖之前对象的属性。
/**
好的,想象一下你有一个玩具箱子,里面有很多玩具。现在你想要一个新的箱子,而且你想把除了最爱的小黄鸭之外的所有玩具都放进新箱子里。在Rust中,我们可以用一个特殊的魔法词“..”,告诉大人我们想这么做。
所以我们对大人说:“请把我的所有玩具,除了小黄鸭,都移到新的箱子里去。”大人就会帮你做这件事。但是一旦玩具移到了新箱子里,你就不能再从旧箱子里拿玩具了,因为它们已经不在那里了。这就像当你把玩具借给朋友后,你就不能再玩那些借出去的玩具了。
而且,你不能像在画画时那样,先画一个太阳,然后又在上面画一个大风筝盖住太阳。在Rust里,一旦你把玩具放到了新箱子,你就决定好了谁去了新箱子,不能改变主意了。
这样的魔法规则帮助确保你的玩具箱子井井有条,每个玩具都知道它应该在哪个箱子里,就像确保你的房间整洁一样。这样你就不会弄丢玩具,也能更容易找到想玩的玩具。
*/
let user2 = User {
username: String::from("hahaha"),
...user
} // rust的整个结构体实例都必须是可变的,才能修改其中的属性,rust不允许只有某些属性是可变的 // build_user 函数返回的User实例,是可变的吗
/**
在Rust中,可变性是由变量的绑定决定的,而不是由函数返回的值决定的。
这意味着,当你的build_user函数返回一个User实例时,它返回的是一个不可变的User实例。
如果你想要修改这个User,你需要在使用它的地方将它绑定到一个可变变量上。
*/
fn build_user(email: String, username: String) -> User {
User {
active: true,
username: username,
email: email,
sign_in_count: 1,
}
}

rust的可不可变是针对变量而不是值的吗?

正是如此!在Rust的世界里,可变性(mutability)是关于变量绑定,而不是值本身。想象一下,你的玩具可以放在两种不同的箱子里:一个是用胶带封死的箱子(不可变的),另一个是可以随时打开加东西的箱子(可变的)。玩具(值)本身没变,但根据你放它的箱子的类型,你可能可以改变箱子里的玩具集合。

所以,在Rust中,当你声明一个变量时,你可以选择它是不是mut的,就是选择用哪种箱子。一旦你决定了,只有mut箱子里的玩具(值)才能被换掉或者修改。如果你试图改变一个用胶带封死的箱子里的玩具,Rust会阻止你,确保你不会意外地弄乱你的玩具集合。这个规则是Rust确保程序安全的方式之一,避免了数据在你不知情的情况下被更改。

这样的设计让Rust程序的行为变得非常可预测,并且减少了程序中出现错误的机会。而且,这还帮助Rust管理内存,因为它可以确切地知道何时某个值不再被需要,以及何时它可以被安全地回收或重新使用。

元组结构体

// 注意,Color和Point是不同的类型,即使其中的元素个数和类型一样
struct Color(i32, i32, i32);
struct Point(i32, i32, i32); fn main() {
let black = Color(0, 0, 0);
let origin = Point(0, 0, 0);
}

没有任何字段的类单元结构体

没有任何字段的类单元结构体有什么用呢?

好比是小朋友的想象游戏,有时候你会拿个香蕉当电话玩,对吧?虽然它就是个香蕉,但在你的游戏里它就变成了电话。在Rust的世界里,一个没有任何字段的结构体就像是那个香蕉电话,它本身没啥用,但你给它赋予了意义。

就像你可以想象香蕉是电话一样,程序员有时需要一些东西来代表某些特别的事情,即使那个东西本身什么都没有。比如说,我们可能有一个空的结构体来表示游戏中的一个事件,它本身不保存任何信息,但它的存在就代表了某个事件发生了。

还有,就像你玩耍时可能会用一个看不见的"盒子"来装你想象中的宝贝一样,程序员也可能会用这种结构体来做出某些选择。例如,它们可以用来打开或关闭软件的某些功能,就像是开关一样。

另外,这种结构体也像是游戏规则里的“它”,比如“你是它”游戏中的“它”。它代表了一个标记或者一个特定的角色,即使它自己没有任何东西。

所以,即使是空空如也的结构体,在Rust这个大型游戏中也有自己的角色和用途。这就是它们的魔法之处!

让我们来看一个Rust中的代码例子,这个例子里我们将使用一个没有任何字段的结构体来做一些有趣的事情。想象一下,我们有一个游戏,游戏里有一些特殊的时刻,比如“游戏开始”或“游戏结束”。我们可以用不同的结构体来代表这些时刻,哪怕这些结构体里面什么都没有!

这里有一个小小的代码片段:

// 定义一个没有字段的结构体,叫做 `GameEvent`。
struct GameStart; // 游戏开始事件
struct GameEnd; // 游戏结束事件 // 我们可以定义一个函数来处理游戏事件。
// 注意这个函数如何接受不同的事件结构体作为参数。
fn process_game_event(event: impl GameEventTrait) {
// 在这个函数里,我们可以根据事件的类型来做不同的事情。
event.print_details();
} // 让我们为这个结构体实现一个Trait,这个Trait允许我们打印出事件的细节。
trait GameEventTrait {
fn print_details(&self);
} // 实现 'GameStart' 结构体的 'GameEventTrait'。
impl GameEventTrait for GameStart {
fn print_details(&self) {
println!("The game has started!");
}
} // 实现 'GameEnd' 结构体的 'GameEventTrait'。
impl GameEventTrait for GameEnd {
fn print_details(&self) {
println!("The game has ended!");
}
} // 现在我们可以创建这些事件的实例并处理它们。
let start = GameStart;
let end = GameEnd; // 处理这些事件
process_game_event(start);
process_game_event(end);

在这个例子中,我们定义了两个没有任何字段的结构体:GameStartGameEnd。它们都实现了一个叫做 GameEventTrait 的trait,这个trait有一个方法 print_details,用于输出一个关于事件的消息。

然后我们有一个 process_game_event 函数,它接受任何实现了 GameEventTrait 的类型的实例。这意味着我们可以传入 GameStartGameEnd 的实例。

当我们调用这个函数并传入 GameStartGameEnd 的实例时,它会打印出相应的开始或结束游戏的消息。

这样的结构体很适合用于事件处理、状态机、消息传递等场景,在这些场景中,标记或者控制流的存在比持有数据更重要。

rust程序设计(3)结构体相关概念和疑问的更多相关文章

  1. C++程序设计之结构体,共用体,枚举和typedef

    [1]结构体的基本功 注意结构体里面可以有很多东西,可以结构体里面包含结构体 #include<iostream> using namespace std; struct Date { i ...

  2. Rust中的结构体及方法语法

    这个可以和类作比较,或是go当中的方法比较. #[derive(Debug)] struct Rectangle { width: u32, height: u32, } impl Rectangle ...

  3. C学习笔记(1)-结构体、预处理与多文件结构程序设计

    一.结构体的定义与使用 #include <stdio.h> //定义结构体(类似模板) typedef struct { char name[50]; int age; char add ...

  4. rust结构体

    //Rust 并不允许只将某个字段标记为可变 struct User { email: String, name:String, age:i32, sex:String, active:bool, } ...

  5. 计算机二级-C语言-程序设计题-190112记录-结构体的遍历和结构体的数据的交换处理,文件的操作。

    //程序设计题:学生的记录由学号和成绩组成,N名学生的数据已在主函数中放入结构体数组s中,请编写函数fun,它的功能是:把分数低的学生数据放在b所指的数组中,注意:分数最低的学生可能不止一个,函数返回 ...

  6. 读书笔记——Windows环境下32位汇编语言程序设计(13)关于EXCEPTION_DEBUG_INFO结构体

    在动手自己尝试编写书上第13章的例子Patch3时,遇到了一个结构体EXCEPTION_DEBUG_INFO. 这个结构体在MASM的windows.inc中的定义和MSDN中的定义不一样. (我使用 ...

  7. 全国计算机等级考试二级教程-C语言程序设计_第14章_结构体、共用体和用户定义类型

    函数的返回值是结构体类型 #define _CRT_SECURE_NO_WARNINGS #include<stdio.h> #include<stdlib.h> struct ...

  8. c语言程序设计案例教程(第2版)笔记(三)—变量、结构体

    零散知识点: 变量        :C语言中,每个变量必须先定义后引用.所谓变量存在是指系统为这个变量分配一块存储空间,此时对变量的操作,就是对变量所对应的存储空间中存放的数据进行操作.人们将变量占据 ...

  9. C语言程序设计(十二) 结构体和共用体

    第十二章 结构体和共用体 当需要表示复杂对象时,仅使用几个基本数据类型显然是不够的 根本的解决方法是允许用户自定义数据类型 构造数据类型(复合数据类型)允许用户根据实际需要利用已有的基本数据类型来构造 ...

  10. Go语言规格说明书 之 结构体类型(Struct types)

    go version go1.11 windows/amd64 本文为阅读Go语言中文官网的规则说明书(https://golang.google.cn/ref/spec)而做的笔记,介绍Go语言的 ...

随机推荐

  1. 将Dubbo注册到Nacos,与DubboAdmin的部署

    王有志,一个分享硬核Java技术的互金摸鱼侠加入Java人的提桶跑路群:共同富裕的Java人 本文是<从 0 开始学 Dubbo>系列文章中应用篇的番外篇. 在这篇文章中我会和大家一起部署 ...

  2. 【题解】Educational Codeforces Round 150(CF1841)

    赛时过了 A-E,然后就开摆了,为什么感觉 C 那么无厘头[发怒][发怒] 排名:25th A.Game with Board 题目描述: Alice 和 Bob 玩游戏,他们有一块黑板.最初,有 \ ...

  3. YUM histoy 与 RPM -qa --last

    查看Linux yum安装包的安装时间,可以使用以下命令: rpm -qa --last 该命令将显示已安装的所有rpm包及其安装日期和时间. 可以使用管道符 '|' 和 grep 命令来查找特定的包 ...

  4. git: failed to push some refs to

    错误原因 没有添加readme文件 解决方案 git pull --rebase origin master 至此问题解决

  5. QMainWindow类中比较重要的方法

    方法和描述 addToolBar():添加工具栏 centralWidget():返回窗口中心的一个空间,未设置时返回NULL menuBar(): 返回主窗口的菜单栏 setCentralWidge ...

  6. quarkus依赖注入之六:发布和消费事件

    欢迎访问我的GitHub 这里分类和汇总了欣宸的全部原创(含配套源码):https://github.com/zq2599/blog_demos 本篇概览 本文是<quarkus依赖注入> ...

  7. Scala的基本使用

    @ 目录 Scala的基本使用 一.基础语法 1.1 变量 1.1.1 var和val 1.1.2 自动类型推断 1.2 数据类型 1.2.1 基础数据类型 1.2.2 增强数据类型 1.3 操作符 ...

  8. MongoDB索引操作和执行计划Explain()详解

    一.索引操作 说明,下面的内容举例时,以"dailyTrip"collection为例. 字段内容如下: { "_id" : ObjectId("63 ...

  9. iOS视图控件的内容显示和离屏渲染流程

    iOS中UI控件内容显示流程 UIKit界面组成 iOS中组成页面的各个元素基本来自UIKit,我们可以修改布局或自定义绘制来修改UIKit元素的默认展示. UIView的页面显示内容有CALayer ...

  10. API接口的对接流程和注意事项

    ​ API接口的对接流程和注意事项 随着互联网技术的发展和数字化时代的到来,API接口已经成为应用程序之间进行数据交换和通信的重要方式.API即应用程序接口,是一种定义.调用和交互的规范,使得不同应用 ...