当前位置: 首页 > news >正文

【Rust练习】11.struct

练习题来自:https://practice-zh.course.rs/compound-types/struct.html

1 对于结构体,我们必须为其中的每一个字段都指定具体的值

// fix the error
struct Person {name: String,age: u8,hobby: String
}
fn main() {let age = 30;let p = Person {name: String::from("sunface"),age,};
}

结构体的初始化,需要将每个字段都赋值才行。

struct Person {name: String,age: u8,hobby: String
}
fn main() {let age = 30;let p = Person {name: String::from("sunface"),age,hobby:String::from("sunface")};
}

题外话,Rust的结构体显然和C或者C++的结构体不太一样,对于C的结构体来说,不存在批量初始化这个说法,结构体都是基本类型,自带初值,赋值需要逐个字段;C++的结构体其实就是public class,初始化方式多种多样,还有面向对象的一系列特征。

而Rust并不是一个面向对象语言(至少它自己不觉得是)

2 🌟 单元结构体没有任何字段。

struct Unit;
trait SomeTrait {// ...定义一些行为
}// 我们并不关心结构体中有什么数据( 字段 ),但我们关心它的行为。
// 因此这里我们使用没有任何字段的单元结构体,然后为它实现一些行为
impl SomeTrait for Unit {  }
fn main() {let u = Unit;do_something_with_unit(u);
} // 填空,让代码工作
fn do_something_with_unit(u: __) {   }

trait是特征,后续会学到这个语法,目前来说可以当它不存在。这里u的类型是Unit

fn do_something_with_unit(u: Unit) {   }

3 🌟🌟🌟 元组结构体看起来跟元组很像,但是它拥有一个结构体的名称,该名称可以赋予它一定的意义。由于它并不关心内部数据到底是什么名称,因此此时元组结构体就非常适合。

// 填空并修复错误
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {let v = Point(__, __, __);check_color(v);
}   fn check_color(p: Color) {let (x, _, _) = p;assert_eq!(x, 0);assert_eq!(p.1, 127);assert_eq!(__, 255);}

复习一下元组的两种访问方式:

  1. 使用索引访问
  2. 指定别名后,使用别名访问

元组结构体也一样,只是类似于CtypedefC++using,给元组起了一个别名。

struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
fn main() {let v = Point(0, 127, 255);check_color(v);
}   fn check_color(p: Point) {let Point(x, y, z) = p;assert_eq!(x, 0);assert_eq!(p.1, 127);assert_eq!(z, 255);}

4 🌟 你可以在实例化一个结构体时将它整体标记为可变的,但是 Rust 不允许我们将结构体的某个字段专门指定为可变的.

// 填空并修复错误,不要增加或移除代码行
struct Person {name: String,age: u8,
}
fn main() {let age = 18;let p = Person {name: String::from("sunface"),age,};// how can you believe sunface is only 18? p.age = 30;// 填空__ = String::from("sunfei");
}

需要让p可变

fn main() {let age = 18;let mut p = Person {name: String::from("sunface"),age,};// how can you believe sunface is only 18? p.age = 30;// 填空p.name = String::from("sunfei");
}

Rust 不允许我们将结构体的某个字段专门指定为可变的

对应C++中的mutable,它的作用是,即使类的成员函数已经声明了const,使用mutable修饰的成员依然可以被修改,也就是“将结构体的某个字段专门指定为可变的”

我们有如下的代码:

struct testMut
{int changeNum() const{num++;return num;}private:int num = 0;
};

编译失败,原因:

testMut.cpp: In member function 'int testMut::changeNum() const':
testMut.cpp:9:9: error: increment of member 'testMut::num' in read-only object9 |         num++;|         ^~~

再给num加上mutable修饰:

mutable int num = 0;

就不会编译失败了。

很难说Rust的这个改进是否有意义,mutable的变量如果不看头文件的定义,再加上你用的IDE比较垃圾(点名eclipse C++),有时候真的意识不到变量被修改了。

5 🌟 使用结构体字段初始化缩略语法可以减少一些重复代码

// 填空
struct Person {name: String,age: u8,
}
fn main() {} fn build_person(name: String, age: u8) -> Person {Person {age,__}
}

答案如下:

struct Person {name: String,age: u8,
}
fn main() {} fn build_person(name: String, age: u8) -> Person {Person {age,name}
}

6 🌟 你可以使用结构体更新语法基于一个结构体实例来构造另一个

// 填空,让代码工作
struct User {active: bool,username: String,email: String,sign_in_count: u64,
}
fn main() {let u1 = User {email: String::from("someone@example.com"),username: String::from("sunface"),active: true,sign_in_count: 1,};let u2 = set_email(u1);
} fn set_email(u: User) -> User {User {email: String::from("contact@im.dev"),__}
}

有点像C++的继承,说实话我第一次知道继承还是从python,Rust的这个更加简洁一点。

fn set_email(u: User) -> User {User {email: String::from("contact@im.dev"),..u}
}

7 🌟🌟 我们可以使用 #[derive(Debug)] 让结构体变成可打印的.


// 填空,让代码工作
#[__]
struct Rectangle {width: u32,height: u32,
}fn main() {let scale = 2;let rect1 = Rectangle {width: dbg!(30 * scale), // 打印 debug 信息到标准错误输出 stderr,并将 `30 * scale` 的值赋给 `width`height: 50,};dbg!(&rect1); // 打印 debug 信息到标准错误输出 stderrprintln!(__, rect1); // 打印 debug 信息到标准输出 stdout
}

对于未继承Debug接口的struct,需要强制支持打印。

// 填空,让代码工作
#[derive(Debug)]
struct Rectangle {width: u32,height: u32,
}fn main() {let scale = 2;let rect1 = Rectangle {width: dbg!(30 * scale), // 打印 debug 信息到标准错误输出 stderr,并将 `30 * scale` 的值赋给 `width`height: 50,};dbg!(&rect1); // 打印 debug 信息到标准错误输出 stderrprintln!("{:?}", rect1); // 打印 debug 信息到标准输出 stdout
}

题外话,C++的format直到最近几代标准才加入,之前各个C++项目基本是在自己用第三方库打印,其实不如这种开箱即用的体验。至于cout?我觉得那个语法挺搞笑的,唯一优点是不需要像printf一样非得声明类型了。

8


// 修复错误
#[derive(Debug)]
struct File {name: String,data: String,
}
fn main() {let f = File {name: String::from("readme.md"),data: "Rust By Practice".to_string()};let _name = f.name;// 只能修改这一行println!("{}, {}, {:?}",f.name, f.data, f);
} 

fname所有权已经转移走了,因此尝试打印name或者f本身都是不被允许的,但是fdata还是可用的。

#[derive(Debug)]
struct File {name: String,data: String,
}
fn main() {let f = File {name: String::from("readme.md"),data: "Rust By Practice".to_string()};let _name = f.name;// 只能修改这一行println!("{}, {}",_name, f.data);
} 

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • Python——模块和包
  • Python 实现电子邮件加密技术解析与实用代码案例
  • 火语言RPA流程组件介绍--提示/弹出/确认消息
  • mysql和pg等数据库之间的数据迁移实战分享
  • MathType常见问题汇总
  • 讲一下如何优化Android应用的启动速度
  • vulhub xxe靶机通关教程
  • PLC边缘计算网关的选择策略-天拓四方
  • 怎么使用PPT倒计时插件?这款在线PPT工具,堪称办公必备!
  • uniapp二维码生成
  • 聚道云软件连接器8月新增应用合集(4)
  • EI论文被引多少次算高引?
  • MFC展锐下载工具设置指定分区下载不擦除 带sheet页的对话框的自动调用。
  • 制作Centos7.9 Live系统镜像
  • VUE 实现三级权限选中与全选
  • [译]前端离线指南(上)
  • 08.Android之View事件问题
  • CentOS7简单部署NFS
  • java中的hashCode
  • JS数组方法汇总
  • MySQL主从复制读写分离及奇怪的问题
  • Python_OOP
  • Rancher如何对接Ceph-RBD块存储
  • 爱情 北京女病人
  • 基于Javascript, Springboot的管理系统报表查询页面代码设计
  • 普通函数和构造函数的区别
  • 使用docker-compose进行多节点部署
  • 小程序测试方案初探
  • 用mpvue开发微信小程序
  • Python 之网络式编程
  • 阿里云IoT边缘计算助力企业零改造实现远程运维 ...
  • 测评:对于写作的人来说,Markdown是你最好的朋友 ...
  • 国内开源镜像站点
  • 回归生活:清理微信公众号
  • ​人工智能书单(数学基础篇)
  • (k8s)Kubernetes 从0到1容器编排之旅
  • (每日一问)计算机网络:浏览器输入一个地址到跳出网页这个过程中发生了哪些事情?(废话少说版)
  • (面试必看!)锁策略
  • (十八)devops持续集成开发——使用docker安装部署jenkins流水线服务
  • (数据大屏)(Hadoop)基于SSM框架的学院校友管理系统的设计与实现+文档
  • (四)鸿鹄云架构一服务注册中心
  • (推荐)叮当——中文语音对话机器人
  • (五)IO流之ByteArrayInput/OutputStream
  • (转)一些感悟
  • ./mysql.server: 没有那个文件或目录_Linux下安装MySQL出现“ls: /var/lib/mysql/*.pid: 没有那个文件或目录”...
  • .NET/C# 编译期能确定的字符串会在字符串暂存池中不会被 GC 垃圾回收掉
  • .NET/C# 使用反射调用含 ref 或 out 参数的方法
  • .NET8.0 AOT 经验分享 FreeSql/FreeRedis/FreeScheduler 均已通过测试
  • .Net插件开发开源框架
  • .pyc文件还原.py文件_Python什么情况下会生成pyc文件?
  • .set 数据导入matlab,设置变量导入选项 - MATLAB setvaropts - MathWorks 中国
  • @entity 不限字节长度的类型_一文读懂Redis常见对象类型的底层数据结构
  • [2013][note]通过石墨烯调谐用于开关、传感的动态可重构Fano超——
  • [2021 蓝帽杯] One Pointer PHP
  • [3D游戏开发实践] Cocos Cyberpunk 源码解读-高中低端机性能适配策略