6.结构体

目录

  • 一、普通结构体(struct)
    • 1.1 说明
    • 1.2 举例
      • 1)结构体定义及访问
      • 2)结构体初化的简单写法
      • 3)结构体更新语法
  • 二、元组结构体(tuple struct)
    • 2.1 概念
    • 2.2 示例
  • 三、类单元结构体(unit-like structs)
    • 3.1 概念
    • 3.2 举例
  • 四、类的使用示例
  • 五、为结构体添加实现方法
    • 5.1 概念
    • 5.2 举例
  • 六、关联函数
    • 6.1 概念
    • 6.2 示例

一、普通结构体(struct)

1.1 说明

  • 需要为所有字段定义名称及类型
  • 结构体可以作为函数的返回值
  • 一旦struct的实例是可变的,那么实例中所有字段都是可变的
  • 实例化时,结构体字段的顺序不需要和它们在声明的的顺序一致

1.2 举例

1)结构体定义及访问

//定义结构体
struct User {
    username: String,
    email: String,
    sing_in_count: u64,
    active: bool,
}

//得到一个结构体实例(未按照定义时的顺序)
fn get_new_user() -> User {
    User {
        email: String::from("ch@163.com"),
        sing_in_count: 86,
        username: String::from("ch@163.com"),
        active: false,
    }
}

fn main() {

    //定义一个可变的结构体实例
    let mut user1 = User {
        email: String::from("xxx@163.com"),
        username: String::from("xxx"),
        active: true,
        sing_in_count: 556,
    };

    let user2 = get_new_user();

    println!("user1: email = {}", user1.email); //xxx@163.com

    user1.email = String::from("yyy@189.com");  //修改可变的值
    println!("user1: email  = {}", user1.email);  //yyy@189.com
    println!("user2: email  = {}", user2.email);  //ch@163.com
}

2)结构体初化的简单写法

  • 前面得到实例时都要重复写字段名称和变量,过于繁琐;
  • 当字段名与字段值对应变量名相同时,就可以使用字段初始化简写的方式;
fn get_new_user(email: String, username: String) -> User {
    User {
        email,
        sing_in_count: 86,
        username,
        active: false,
    }
}

3)结构体更新语法

  • 通过改变旧实例中少部分值来创建一个新的结构体实例可以使用结构体更新语法
  • .. 旧实例语法指定了剩余未显式设置值的字段应有与给定实例对应字段相同的值;
    *..旧实例必须放在最后,以指定其余的字段应从旧实例的相应字段中获取其值,但我们可以选择以任何顺序为任意字段指定值,而不用考虑结构体定义中字段的顺序;
  • ..旧实例后不能加逗号;
  • 要注意所有权转移的问题
struct User {
    username: String,
    email: String,
    sing_in_count: u64,
    active: bool,
}

fn get_new_user() -> User {
    let username = String::from("ch@163.com");
    let email = String::from("ch@163.com");
    User {
        username,
        email,
        sing_in_count: 86,
        active: false,
    }
}

fn main() {
    let user1 = get_new_user();

    //未采用更新语法
    let user2 = User{
        username: String::from("user2"),
        email: String::from("user2@163.com"),
        sing_in_count: user1.sing_in_count,
        active: user1.active,
    };

    //采用结构体更新语法
    let user3 = User{
        username: String::from("user3"),
        ..user1  //不能写逗号,其它的用user1的赋值
    };
    
    // println!("user1.username = {}", user1.email); //所有权已经转移到user3,所以这里不能使用

    println!("user2.username = {}, sing_in_count = {}", user2.username, user2.sing_in_count);
    println!("user3.username = {}, sing_in_count = {}", user3.username, user3.sing_in_count);
}

二、元组结构体(tuple struct)

2.1 概念

  • 定义与元组类似的结构体,称为元组结构体
  • 元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型
  • 当想给整个元组取一个名字,并使元组成为与其他元组不同的类型时,可以使用元组结构体;
  • 要定义元组结构体,以 struct 关键字和结构体名开头并后跟元组中的类型;

2.2 示例

fn main() {
    struct Color(i32, i32, i32);
    struct Point(i32, i32, i32);

    let black = Color(3, 4, 5);
    let origin = Point(33, 15, 14);

    println!("{} {} {}", black.0, black.1, black.2);
    println!("{} {} {}", origin.0, origin.1, origin.2);
}

三、类单元结构体(unit-like structs)

3.1 概念

  • 类单元结构体是一个没有任何字段的结构体
  • 类似于 (),即单元类型(只有一个值,被称为单元值);
  • 类单元结构体常常在想要在某个类型上实现 trait 但不需要在类型中存储数据的时候发挥作用;

3.2 举例

struct AlwaysEqual;

fn main() {
    let subject = AlwaysEqual;
}
  • 使用struct关键字定义 AlwaysEqual,以分号结尾;
  • 在main函数中,以代码所示的方法获得 AlwaysEqual 的实例变量 subject;
  • 下一步将实现这个类型的行为,即每个实例始终等于每一个其他类型的实例,也许是为了获得一个已知的结果以便进行测试。现在不需要任何数据来实现这种行为。在以后的文章里将会看到如何定义特性并在任何类型上实现它们,包括类单元结构体。

四、类的使用示例

#[derive(Debug)]
struct Rectangle{
    width: u32,
    height: u32,
}

//只传递引用,因此不会获取传入变量的所有权
fn area(rect: &Rectangle) -> u32 {
    rect.width * rect.height
}

fn main() {
    let rc = Rectangle{
        width: 53,
        height: 20,
    };

    println!("area = {}", area(&rc));
    println!("rc = {:#?}", rc)
}
  • 代码计算长方体的面积;
  • area传入的是引用,因此不会获得变量的所有权;
  • #[derive(Debug)]与println的{:#?}配合使用是为了查看实体化后rc的值,如果把前者取消并且使用println!("rc={}",rc)打印结果,会得到如下错误
    在这里插入图片描述
    按照说明修改println!的参数再编译会得到如下错误
    在这里插入图片描述
    因此,根据提示一步步修改就会得到正确的结果

五、为结构体添加实现方法

5.1 概念

  • 使用fn关键字和名称声明,可以拥有参数和返回值;
  • 方法在结构体的上下文中被定义(或者是枚举或 trait 对象的上下文),并且第一个参数总是 self,代表调用该方法的结构体实例;
  • 一般将方法的第一个参数写为&self,只希望能够读取结构体中的数据,而不是写入;
  • 想要在方法中改变调用方法的实例,需要将第一个参数改为&mut self
  • 通过仅仅使用 self 作为第一个参数来使方法获取实例的所有权是很少用的;该功能通常用在当方法将 self 转换成别的实例的时候,想要防止调用者在转换之后使用原始的实例。

5.2 举例

  • area方法实现了面积的计算;
  • can_hold方法计算当前对象是否能够包围住第二个Rectangle对象的实例;
#[derive(Debug)]
struct Rectangle{
    width: u32,
    height: u32,
}

impl Rectangle{
    fn area(&self) -> u32{
        self.width * self.height
    }

    fn can_hold(&self, src: &Rectangle) -> bool{
        self.width >= src.width && self.height >= src.height
    }
}

fn main() {
    let rc = Rectangle{
        width: 53,
        height: 20,
    };

    let rc2 = Rectangle{
        width: 51,
        height: 20,
    };

    println!("{}", rc.can_held(&rc2));
}

六、关联函数

6.1 概念

  • 所有在 impl 块中定义的函数被称为关联函数;
  • 可以定义不以 self为第一参数的关联函数(类似于类的静态函数),String::from就是一个关联函数;

6.2 示例

使用关联函数创建正文形并计算面积。

#[derive(Debug)]
struct Rectangle{
    width: u32,
    height: u32,
}

impl Rectangle{
    fn area(&self) -> u32{
        self.width * self.height
    }

    fn square(size: u32) -> Rectangle{
        Rectangle{
            width: size,
            height: size,
        }
    }
}

fn main() {
    let rc = Rectangle::square(3);
    println!("rc.area = {}", rc.area());
}

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

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

相关文章

程序猿大战Python——容器——字符串

字符串介绍 什么是Python容器 目标:了解Python容器是什么? 在现实生活中,我们知道容器是用来存放东西的,比如实验室里的烧杯等。 类似的,在Python中的容器是用来存放数据的。 与此同时,为了操作方便&…

Java毕业设计 基于springboot vue大学生助学贷款管理系统

Java毕业设计 基于springboot vue大学生助学贷款管理系统 SpringBoot 大学生助学贷款管理系统 功能介绍 学生 登录 注册 个人中心 修改密码 个人信息 助学贷款 申请贷款 放贷信息 还贷信息 公告资讯 学校 登录 注册 个人中心 修改密码 个人信息 助学贷款管理 申请贷款管理 公…

java:mybatis查询时自动添加tenantId和deleted查询条件

# 参考资料 https://blog.csdn.net/chenhz2284/article/details/139606486?spm1001.2014.3001.5502 # 示例代码 【pom.xml】 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId>&l…

纳税信用评级:企业的“金字招牌”

在快速发展的市场经济中&#xff0c;企业的信用状况越来越成为其竞争力的重要组成部分。而在税务领域&#xff0c;纳税信用评级更是衡量一个企业是否诚信经营的重要指标。今天&#xff0c;就让我们一起来深入了解纳税信用评级的相关知识。 一、纳税信用评级是什么&#xff1f;…

Python中的钩子函数(hooks)介绍使用

什么是hook&#xff1f; 钩子函数&#xff0c;顾名思义&#xff0c;就是把我们自己实现的自定义函数在某一时刻挂接到目标挂载点上去执行。 1. hook函数&#xff0c;就是我们自己实现的函数&#xff0c;函数类型与挂载点匹配&#xff08;返回值&#xff0c;参数列表&#xff0…

Fake news detection: A survey of graph neural network methods

abstract 各种社交网络的出现产生了大量的数据。捕获、区分和过滤真假新闻的有效方法变得越来越重要&#xff0c;特别是在 COVID-19 大流行爆发之后。本研究对假新闻检测系统的图神经网络 (GNN) 的现状和挑战进行了多方面、系统的回顾&#xff0c;并概述了使用 GNN 实现假新闻…

C++STL初阶(4):初识vector

vector是一个类模版&#xff0c;是一个顺序容器&#xff0c;底层思维就是顺序表&#xff0c;而顺序表的本质就是一个可以改变size的数组。本篇基于string的学习基础&#xff0c;我们对vector进行一个大致的了解和学习 1.基本介绍 1. vector 是表示可变大小数组的序列容器&#…

老生常谈!程序员为什么要阅读源代码?

大家好&#xff0c;我是码农先森。 阅读源码这是一个老生常谈的话题了&#xff0c;但又是很多人想做又没有付出行动的事情。前段时间我研究了 Swoole 的源代码&#xff0c;并且输出了系列的源码分析文章「感兴趣的朋友可以翻阅以前的文章」。虽然这个过程很枯燥和艰难&#xf…

css font-family

知乎的font-family的设置理解 -apple-system, BlinkMacSystemFont 这两个值是为了确保在macOS和iOS系统上能够使用系统默认字体进行文本渲染。-apple-system特别为Safari浏览器设计&#xff0c;而BlinkMacSystemFont则主要针对基于Chromium的浏览器&#xff08;如Chrome&#…

【Linux】shell——条件判断test,各种运算符,expr

条件判断——test 真——0 假——1 test expression or [ expression ] 整数运算符 字符串运算符 -z 长度是否为0 -n 长度是否不为0 str1 str2 str1 ! str2 补 &&-->逻辑与&#xff0c;前面为真后面才会执行 || -->逻辑或&#xff0c;前面为假后面才…

京东网页html+css简单制作1(附带源码和素材)

一.代码效果展示 代码html骨架结构分为头部top,颈部banner&#xff0c;中间部分main,腿部fortet-image,尾部fortter&#xff0c;五部分组成&#xff0c;从上至下&#xff0c;从左到右结构。&#xff08;总体因为没设计版心&#xff0c;所以位置比较乱&#xff09; 其中中部mai…

云动态摘要 2024-06-11

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 [低至1折]腾讯混元大模型产品特惠 腾讯云 2024-06-06 腾讯混元大模型产品特惠,新用户1折起! 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器ECS试用产品续用 最新产品更新 云服务器运维监…

设计模式-代理模式(结构型)

代理模式 代理模式是一种结构型模式&#xff0c;它可以通过一个类代理另一个类的功能。代理类持有被代理类的引用地址&#xff0c;负责将请求转发给代理类&#xff0c;并且可以在转发前后做一些处理 图解 角色 抽象主题&#xff08;Subject&#xff09;: 定义代理对象和被代理…

【安卓13 源码】Input子系统(2) - input系统与应用进程通信

点击手机屏幕&#xff0c;可以分发input 事件到对应的view&#xff0c;由上一节知道input 是运行在system 进程的&#xff0c;那应用进程与系统进程是如何通讯的呢&#xff0c;相信本文可以给到一点小小的答案。 先给个结论&#xff1a;应用在resume 的时候才去建立与input 服…

项目部署(前后端)

一&#xff1a;多环境概念&#xff1a; 借鉴来源&#xff1a;多环境设计_程序员鱼皮-多环境设计-CSDN博客 为什么需要多环境&#xff1a; 第一个例子&#xff1a;我们可以设想&#xff0c;我们肯定玩过王者荣耀&#xff0c;且王者荣耀也一直在不断更新&#xff0c;如果按我们…

cleanmymac清理时要一直输入密码 CleanMyMac X一直提示输入密码的解决方案

CleanMyMac X是一款专业的Mac清理软件&#xff0c;可智能清理mac磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软件&#xff0c;修复系统漏洞&#xff0c;一键扫描和优化Mac系统。 在使用Cle…

【人工智能基础学习】Andrew Ng-机器学习基础笔记

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…

HyperSnap软件最新版下载-HyperSnap官方最新版附加详细安装步骤

​HyperSnap是一个老牌优秀的屏幕截图工具&#xff0c;全新界面&#xff0c;不仅能抓取标准桌面程序&#xff0c;还能抓取 DirectX, 3Dfx Glide的 游戏视频或 DVD 屏幕图&#xff0c;能以 20 多种图形格式&#xff08;包括&#xff1a;BMP, GIF,JPEG, TIFF, PCX等&#xff09;保…

鸿蒙开发:应用组件跨设备交互(流转)【跨端迁移】

跨端迁移 概述 在用户使用设备的过程中&#xff0c;当使用情境发生变化时&#xff08;例如从室内走到户外或者周围有更适合的设备等&#xff09;&#xff0c;之前使用的设备可能已经不适合继续当前的任务&#xff0c;此时&#xff0c;用户可以选择新的设备来继续当前的任务&a…

C盘爆满?教你轻松清理无故产生的大量临时文件!

在电脑操作中&#xff0c;用户发现自己系统C盘爆满了&#xff0c;无缘无故产生了大量的临时文件&#xff0c;导致电脑运作变得卡顿&#xff0c;但不知道要怎么操作才能解决这个问题&#xff1f;接下来小编给小伙伴们带来不同的解决方法&#xff0c;轻松清理电脑上的临时文件。 …