结构体

结构体可以创建更复杂数据类型,大写字母开头并且驼峰命名法.生命周期和泛型都写在 <> 里,先生命周期后泛型,用,分隔,只有struct的最后一个字段可能拥有一个动态大小类型;其它字段则不可以拥有动态大小类型。枚举变量不可以用动态大小类型作为数据。

  • 结构体里的引用字段必须要有显式的生命周期
  • 一个被显式写出生命周期的结构体,其自身的生命周期一定小于等于其显式写出的任意一个生命周期

Rust 的结构体三种:

  • C风格结构体
  • 元組结构体
  • 单元结构体

C风格结构体

  1. struct Point {
  2. x: i32,
  3. y: i32,
  4. }
  5. fn main() {
  6. let origin = Point { x: 0, y: 0 }; // origin: Point
  7. let mut do = Point { x: 1, y: 2 };
  8. do.x = 5;
  9. println!("The origin is at ({}, {})", origin.x, origin.y);
  10. println!("The origin is at ({}, {})", do.x, do.y);
  11. }

Rust 不支持结构体字段可变性,可变性是绑定的一个属性。

  1. struct Point {
  2. x: i32,
  3. y: i32,
  4. }
  5. fn main() {
  6. let mut point = Point { x: 0, y: 0 };
  7. point.x = 5;
  8. let point = point; // now immutable
  9. point.y = 6; // this causes an error
  10. }

结构体包含&mut指针,它会给你一些类型的可变性:

  1. struct Point {
  2. x: i32,
  3. y: i32,
  4. }
  5. struct PointRef<'a> {
  6. x: &'a mut i32,
  7. y: &'a mut i32,
  8. }
  9. fn main() {
  10. let mut point = Point { x: 0, y: 0 };
  11. {
  12. let r = PointRef { x: &mut point.x, y: &mut point.y };
  13. *r.x = 5;
  14. *r.y = 6;
  15. }
  16. assert_eq!(5, point.x);
  17. assert_eq!(6, point.y);
  18. }

元组结构体

元组结构体有着结构体名称提供的含义,但没有具体的字段名,只有字段的类型。

  1. struct Color(i32, i32, i32);
  2. struct Point(i32, i32, i32);
  3. //这里`black`和`origin`并不相等,即使它们有一模一样的值:
  4. let black = Color(0, 0, 0);
  5. let origin = Point(0, 0, 0);

当元组结构体只有一个元素时。我们管它叫新类型newtype),创建了一个与元素相似的类型:

  1. struct Inches(i32);
  2. let length = Inches(10);
  3. let Inches(integer_length) = length;
  4. println!("length is {} inches", integer_length);

可以通过一个解构let来提取内部的整型,let Inches(integer_length)integer_length赋值为10

单元结构体

定义一个没有任何成员的结构体,类似于 (),即 unit 类型。类单元结构体常常在你想要在某个类型上实现 trait 但不需要在类型内存储数据的时候发挥作用。

  1. struct Electron {}
  2. struct Proton;
  3. // Use the same notation when creating an instance.
  4. let x = Electron {};
  5. let y = Proton;

简写语法

参数名与字段名都完全相同,我们可以使用 字段初始化简写语法,这样其行为与之前完全相同

  1. fn build_user(email: String, username: String) -> User {
  2. User {
  3. email, // 简写: email: email,
  4. username, // 简写: username: username,
  5. active: true,
  6. sign_in_count: 1,
  7. }
  8. }

更新语法

一个包含..struct表明你想要使用一些其它结构体的拷贝的一些值。例如:

  1. struct Point3d {
  2. x: i32,
  3. y: i32,
  4. z: i32,
  5. }
  6. let mut point = Point3d { x: 0, y: 0, z: 0 };
  7. point = Point3d { y: 1, .. point };

这给了point一个新的y,不过保留了xz的值。这也并不必要是同样的struct,你可以在创建新结构体时使用这个语法,并会拷贝你未指定的值:

  1. struct Point3d {
  2. x: i32,
  3. y: i32,
  4. z: i32,
  5. }
  6. let origin = Point3d { x: 0, y: 0, z: 0 };
  7. let point = Point3d { z: 1, x: 2, .. origin };