[ Rust笔记 三] 基础-复合数据类型

tuple

1
2
3
4
5
6
7
8
9
10
11
   let a = (1i32, false);        // 元组中包含两个元素,第一个是i32类型,第二个是bool类型
let b = ("a", (1i32, 2i32)); // 元组中包含两个元素,第二个元素本身也是元组,它又包含了两个元素
let a = (0, ); // a是一个元组,它有一个元素
let b = (0); // b是一个括号表达式,它是i32类型

let p = (1i32, 2i32);
let (a, b) = p;

let x = p.0;
let y = p.1;
println!("{} {} {} {}", a, b, x, y);

元组内部也可以一个元素都没有。这个类型单独有一个名字,叫unit(单元类型)​:

1
let empty : () = ();

unit类型是Rust中最简单的类型之一,也是占用空间最小的类型之一。空元组和空结构体struct Foo;一样,都是占用0内存空间。

1
2
3
4
5
fn main() {
println!("size of i8 {}" , std::mem::size_of::<i8>());
println!("size of char {}" , std::mem::size_of::<char>());
println!("size of '()' {}" , std::mem::size_of::<()>());
}

struct

1
2
3
4
struct Point {
x: i32,
y: i32,
}

初始化,类json语法初始化

1
2
3
4
fn main() {
let p = Point { x: 0, y: 0};
println!("Point is at {} {}", p.x, p.y);
}

使用局部变量初始化

1
2
3
4
5
6
7
8
fn main() {
// 刚好局部变量名字和结构体成员名字一致
let x = 10;
let y = 20;
// 下面是简略写法,等同于 Point { x: x, y: y },同名字的相对应
let p = Point { x, y };
println!("Point is at {} {}", p.x, p.y);
}

使用语法糖赋值

1
2
3
4
5
6
7
8
9
10
11
12
struct Point3d {
x: i32,
y: i32,
z: i32,
}
fn default() -> Point3d {
Point3d { x: 0, y: 0, z: 0 }
}
// 可以使用default()函数初始化其他的元素
// ..expr 这样的语法,只能放在初始化表达式中,所有成员的最后最多只能有一个
let origin = Point3d { x: 5, ..default()};
let point = Point3d { z: 1, x: 2, ..origin };

空结构体

1
2
3
4
//以下三种都可以,内部可以没有成员
struct Foo1;
struct Foo2();
struct Foo3{}

tuple struct

1
2
struct Color(i32, i32, i32);
struct Point(i32, i32, i32);
1
2
3
4
5
6
7
8
9
10
11
12
13
struct T1 {
v: i32
}
// define tuple struct
struct T2(i32);
fn main() {
let v1 = T1 { v: 1 };
let v2 = T2(1); // init tuple struct
let v3 = T2 { 0: 1 }; // init tuple struct
let i1 = v1.v;
let i2 = v2.0;
let i3 = v3.0;
}

enum

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
//内部可能是一个i32型整数,或者是f32型浮点数
enum Number {
Int(i32),
Float(f32),
}

fn read_num(num: &Number) {
match num {
// 如果匹配到了 Number::Int 这个成员,那么value的类型就是 i32
&Number::Int(value) => println!("Integer {}", value),
// 如果匹配到了 Number::Float 这个成员,那么value的类型就是 f32
&Number::Float(value) => println!("Float {}", value),
}
}

fn main() {
let n: Number = Number::Int(10);
read_num(&n);
}

1
2
3
4
5
6
7

fn main() {
// 使用了泛型函数的调用语法,请参考第21章泛型
println!("Size of Number: {}", std::mem::size_of::<Number>());
println!("Size of i32: {}", std::mem::size_of::<i32>());
println!("Size of f32: {}", std::mem::size_of::<f32>());
}

打印结果
Size of Number: 8
Size of i32: 4
Size of f32: 4

max(sizeof(i32), sizeof(f32)​)= max(4byte, 4 byte)= 4 byte。
而它总共占用的内存是8 byte,多出来的4 byte就是用于保存类型标记的。

1
2
3
4
5
6
7
8
9
10
11
12
enum Message {
Quit,
ChangeColor(i32, i32, i32),
Move { x: i32, y: i32 },
Write(String),
}
let x: Message = Message::Move { x: 3, y: 4 };
enum BoardGameTurn {
Move { squares: i32 },
Pass,
}
let y: BoardGameTurn = BoardGameTurn::Move { squares: 1 };

类型递归定义

错误的定义

1
2
3
4
struct Recursive {
data: i32,
rec: Recursive,
}

编译报错

error[E0072]: recursive type `Recursive` has infinite size
  --> test.rs:2:1
  |
2 | struct Recursive {
  | ^^^^^^^^^^^^^^^^ recursive type has infinite size
3 |     data: i32,
4 |     rec: Recursive,
  |     -------------- recursive without indirection
  |
  = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make

Recursive representable

size_of::() == 4 + size_of::(),无法计算。

1
2
3
4
struct Recursive {
data: i32,
rec: Box<Recursive>,
}

指针存在固定大小,所以能计算出。