Rust---复合数据类型之结构体

news2024/11/20 11:52:01

目录

  • 结构体的使用
    • 输出结果
  • 结构体简化创建
  • 结构体更新语法
  • 元组结构体
  • 单元结构体(unit struct)
  • 结构体中的引用
  • 使用#[derive(Debug)]
    • 再次介绍
  • 代码综合展示

与元组不同的是,结构体可以为内部的每个字段起一个富有含义的名称,因此无需依赖这些字段的顺序就可以来访问和解析它们。

结构体的使用

// 定义一个结构体 Person
struct Person {
    name: String,
    age: u32,
}

// 为 Person 结构体实现方法
impl Person {
    fn greet(&self) {
        println!("Hello, my name is {}.", self.name);
    }
}

fn main() {
    // 创建一个 Person 结构体实例
    let mut person1 = Person {
        name: String::from("Alice"),
        age: 30,
    };

    // 修改 Person 结构体字段
    // 必须要将结构体实例声明为可变的,才能修改其中的字段,Rust 不支持将某个结构体某个字段标记为可变。
    person1.name = String::from("Amy");
    
    // 访问 Person 结构体字段
    println!("Name: {}", person1.name);
    println!("Age: {}", person1.age);

    // 调用 Person 结构体方法
    person1.greet();
}

输出结果

在这里插入图片描述

结构体简化创建

fn build_user(email: String, username: String) -> User {
    User {
        email,//当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化
        username,//当函数参数和结构体字段同名时,可以直接使用缩略的方式进行初始化
        active: true,
        sign_in_count: 1,
    }
}

结构体更新语法

  • .. 语法表明凡是我们没有显式声明的字段,全部从 user1 中自动获取。
  • 需要注意的是 ..user1 必须在结构体的尾部使用。
  let user2 = User {
        email: String::from("another@example.com"),
        ..user1
    };
  • 结构体更新语法跟赋值语句 = 非常相像,结果是,username 所有权被转移给了 user2,导致了 user1 无法再被使用。
  • 把结构体中具有所有权的字段转移出去后,将无法再访问该字段,但是可以正常访问其它的字段。

元组结构体

  • 元组结构体在某些情况下比普通结构体更方便,特别是当您只需要一个简单的数据结构来存储几个字段时。元组结构体可以帮助您更清晰地表达代码的意图,并且具有元组的轻量性和灵活性。
  • 结构体的字段可以没有名称,这种结构体长得很像元组。
// 定义一个类似元组的结构体 Color,表示颜色
struct Color(i32, i32, i32);

// 定义一个类似元组的结构体 Point,表示三维空间中的点
struct Point(i32, i32, i32);

fn main() {
    // 创建一个 Color 结构体实例,表示黑色
    let black = Color(0, 0, 0);

    // 创建一个 Point 结构体实例,表示原点
    let origin = Point(0, 0, 0);

    // 访问 Color 结构体的字段
    println!("Black: ({}, {}, {})", black.0, black.1, black.2);

    // 访问 Point 结构体的字段
    println!("Origin: ({}, {}, {})", origin.0, origin.1, origin.2);
}

单元结构体(unit struct)

  • 它不包含任何字段。单元结构体的定义非常简单,只是由结构体关键字 struct 后面跟结构体的名称构成,例如:
struct UnitStruct;
  • 单元结构体在 Rust 中主要用于表示不需要存储数据的类型,通常用作占位符、类型标记或模块化设计中的辅助类型。

结构体中的引用

  • 如果想在结构体中使用一个引用,就必须加上生命周期。
  • 生命周期能确保结构体的作用范围要比它所借用的数据的作用范围要小。

使用#[derive(Debug)]

  • 如果使用 {} 来格式化输出,那对应的类型就必须实现 Display 特征,结构体不默认实现 Display 特征。因此下面的代码会报错:
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {}", rect1);
}
  • 如果改为:println!("rect1 is {:?}", rect1);
// 会提醒我们没有实现debug特征
error[E0277]: `Rectangle` doesn't implement `Debug`
  • 正确使用方法:
#[derive(Debug)]// 加上这一个东西
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    let rect1 = Rectangle {
        width: 30,
        height: 50,
    };

    println!("rect1 is {:?}", rect1);
}

再次介绍

  • Rust 中,#[derive(Debug)] 是一个非常方便的属性,用于自动实现 Debug traitDebug trait 是一个用于打印调试信息的 trait,通过实现这个 trait,可以使用 println!("{:?}", variable); 这样的方式来输出变量的调试信息,而不需要手动实现 Debug traitfmt 方法。
  • #[derive(Debug)] 的使用可以简化代码,并让我们更方便地输出结构体、枚举等类型的调试信息。

代码综合展示

// 定义一个结构体 Person
struct Person {
    name: String,
    age: u32,
}

// 为 Person 结构体实现方法
impl Person {
    fn greet(&self) {
        println!("Hello, my name is {}.", self.name);
    }
}

// 定义一个元组结构体 Point
struct Point(i32, i32);

// 定义一个结构体 Rectangle,并衍生 Debug 特性
#[derive(Debug)]
struct Rectangle {
    width: u32,
    height: u32,
}

fn main() {
    // 创建一个 Person 结构体实例
    let person1 = Person {
        name: String::from("Alice"),
        age: 30,
    };

    // 访问 Person 结构体字段
    println!("Name: {}", person1.name);
    println!("Age: {}", person1.age);

    // 调用 Person 结构体方法
    person1.greet();

    // 创建一个可变 Person 结构体实例
    let mut person2 = Person {
        name: String::from("Bob"),
        age: 25,
    };

    // 修改 Person 结构体字段
    person2.age = 26;

    // 创建一个元组结构体实例
    let origin = Point(0, 0);

    // 创建一个 Rectangle 结构体实例
    let rect = Rectangle {
        width: 10,
        height: 20,
    };

    // 打印 Rectangle 结构体实例,使用 Debug 特性
    println!("{:?}", rect);
}

输出结果:【这个警告实在是不知道怎么修改,明明已经使用println!("{:?}", variable);了】
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Qt+OpenGL_part1

OpenGL,Qt实现:1入门篇(已更完)_哔哩哔哩_bilibili OpenGL3.3以上是现代模式(可编程管线): 状态机 状态设置函数(State-changing Function) 状态应用函数 (State-using Function) OpenGL的状态…

VB 通过COM接口解析PSD文件

最近有PS测评的需求,故而想到了解析psd文件,目的就是为了获取文档信息和图层信息;获取PS的图像信息有很多方式,有过程性的,比如监听PS的各种操作事件;有结果性的,比如本文写的解析PSD文件。 0.…

易语言创建数据库

易语言是一门中文编程语言,由国人开发,虽然比较冷门,但是在有些场合却非常流行,比如自动化脚本,还有开发外挂。 以下将用一个简单的用户表,演示易语言创建数据库的几种方式: 1. 使用菜单创建数…

无人售货奶柜:开启便捷生活的新篇章

无人售货奶柜:开启便捷生活的新篇章 在这个快节奏的现代生活中,科技的革新不仅为我们带来了前所未有的便利,更在不经意间改变着我们的日常。其中,无人售货技术的出现,尤其是无人售货奶柜,已经成为我们生活…

pta 1086 就不告诉你

1086 就不告诉你 分数 15 全屏浏览 切换布局 作者 CHEN, Yue 单位 浙江大学 做作业的时候,邻座的小盆友问你:“五乘以七等于多少?”你应该不失礼貌地围笑着告诉他:“五十三。”本题就要求你,对任何一对给定的正整数…

图像拼接——最小割准则提取拼接缝

一、最大流问题与Ford-Fulkerson算法介绍 二、最大流与最小割 显然,我们有对任意一个割,穿过该割的净流量上界就是该割的容量,即不可能超过割的容量。所以网络的最大流必然无法超过网络的最小割。最小割是指割的容量最小,最大流是指网络当中最大的净流量,简单的例子s是水龙…

Vue3从入门到实战:路由知识点

本人在B站上关于vue3的尚硅谷的课程,以下是整理一些笔记。 1.两个知识点 1.路由组件通常存放在pages 或 views文件夹,一般组件通常存放在components文件夹。 组件可以分为: 1. 一般组件:亲手写标签出来的 2. 路由组件&#…

武汉星起航电子商务公司领航跨境电商新纪元,助力品牌走向全球

在全球经济一体化的时代背景下,跨境电商正成为推动国际贸易增长的重要力量。武汉星起航电子商务有限公司,作为一家专注于提供一站式解决方案的跨境电商服务商,凭借其丰富的实战经验和专业团队,在行业中取得了令人瞩目的成绩。 自…

获取天翼网关TEWA-708E超级管理员密码

Download RouterPassView 参考:破解光猫超级管理员密码(网关型号:TEWA-708E) - 知乎

Linux集群(一)Nginx搭建

目录 一、Nginx介绍 1.什么是Nginx 2.Nginx的特点 二、Nginx配置 1.jdk的安装 1.1检查jdk版本 1.2上传并安装jdk 2.安装Tomcat 3.下载Nginx 3.1安装依赖包 ​编辑 3.2安装Nginx 3.3运行 三、Nginx中的常用命令​编辑 一、Nginx介绍 1.什么是Nginx Nginx(…

C++初阶:stack和queue使用及模拟实现

stack的介绍和使用 stack的介绍 堆栈 - C 参考 (cplusplus.com) 翻译 : 1. stack 是一种容器适配器,专门用在具有后进先出操作的上下文环境中,其删除只能从容器的一端进行元素的插入与提取操作。 2. stack 是作为容器适配器被实现的,容器…

【Java笔记】多线程0:JVM线程是用户态还是内核态?Java 线程与OS线程的联系

文章目录 JVM线程是用户态线程还是内核态线程什么是用户态线程与内核态线程绿色线程绿色线程的缺点 线程映射稍微回顾下线程映射模型JVM线程映射 线程状态操作系统的线程状态JVM的线程状态JVM线程与OS线程的状态关系 Reference 今天复盘一下Java中,JVM线程与实际操作…

大模型学习笔记一

前言 随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。 一、AI是什么? 二、大模型能干什么 大模型,全称「大语言模型」,英文「Large…

栈的应用——用栈实现算数混合运算表达式的计算

1、单目运算符双目运算符 算数运算符分为单目运算符和双目运算符等 单目运算符只需要一个操作数,双目运算符需要两个操作数 双目运算符最常见:常见的算术运算符:*/,比较运算符:<>=等等以下是一些单目运算符:正号 (+): 用于表示正数或给数值一个正号。例如:+5 仍然…

MySql 实战大数据查询-(表分区实现)

一 mysql分区&#xff1a; 分区是将单个表按照某种规则划分成多个子集&#xff0c;每个子集称为一个分区。常见的分区策略包括按照时间范围、范围值、列表等进行分区。 优点&#xff1a; 查询性能更好&#xff0c;涉及分区键的查询&#xff0c;数据库引擎可以只扫描特定分区&…

最优算法100例之30-表示数值的字符串

专栏主页&#xff1a;计算机专业基础知识总结&#xff08;适用于期末复习考研刷题求职面试&#xff09;系列文章https://blog.csdn.net/seeker1994/category_12585732.html 题目描述 请实现一个函数用来判断字符串是否表示数值&#xff08;包括整数和小数&#xff09;。例如&a…

卷积篇 | YOLOv8改进之引入全维度动态卷积ODConv | 即插即用

前言:Hello大家好,我是小哥谈。ODConv是一种关注了空域、输入通道、输出通道等维度上的动态性的卷积方法,一定程度上讲,ODConv可以视作CondConv的延续,将CondConv中一个维度上的动态特性进行了扩展,同时了考虑了空域、输入通道、输出通道等维度上的动态性,故称之为全维度…

LeetCode第六题:Z 字形变换 【6/1000 python】

&#x1f464;作者介绍&#xff1a;10年大厂数据\经营分析经验&#xff0c;现任大厂数据部门负责人。 会一些的技术&#xff1a;数据分析、算法、SQL、大数据相关、python 作者专栏每日更新&#xff1a; LeetCode解锁1000题: 打怪升级之旅 LeetCode解锁1000题: 打怪升级之旅htt…

springboot实战---7.springboot制作Docker镜像

&#x1f388;个人主页&#xff1a;靓仔很忙i &#x1f4bb;B 站主页&#xff1a;&#x1f449;B站&#x1f448; &#x1f389;欢迎 &#x1f44d;点赞✍评论⭐收藏 &#x1f917;收录专栏&#xff1a;SpringBoot &#x1f91d;希望本文对您有所裨益&#xff0c;如有不足之处&…

七、Promethus监控系统

一、普罗米修斯监控系统 1、为什么需要监控&#xff1a; ① 实时收集数据&#xff1a;监控工具能够实时收集关于系统、应用、网络等各方面的数据&#xff0c;包括性能指标、错误日志、用户行为等。 ② 及时发现问题&#xff1a;通过实时数据收集和分析&#xff0c;监控系统能…