Rust学习之旅——基本数据结构类型

结构体

一个 struct 就是一些字段的集合。

字段是一个与数据类型相关联的数据值。它的值可以是基本类型或者是结构体类型。

它的定义就像是给编译器的蓝图,告诉编译器如何在内容中布局彼此相邻的字段。

struct SeaCreature {
	// String 是个结构体
	animal_type: String,
	name: String,
	arms: i32,
	legs: i32,
	weapon: String,
}

方法调用

与函数(function)不同,方法(method)是与特定数据类型关联的函数

静态方法-属于某个类型,调用时使用 :: 运算符
动态方法-属于某个类型的实例,调用时使用 . 运算符

fn main() {
	// 使用静态方法来创建一个String实例
	let s = String::from("Hello world!");
	// 使用实例来调用动态方法
	println!("{} is {} characters long.", s, s.len());
}

内存

Rust 程序有3个存放数据的内存区域:

  • 数据内存 - 对于固定大小静态(即在整个程序生命周期中都存在)的数据。比如上一例子中的文本(例如“Hello world”),该文字的字节只能读取,因为它们位于该区域中。编译器对于这类数据做了很多优化,由于位置已知且固定,因此通常认为编译器使用起来非常快。
  • 栈内存 - 对于在函数中声明为变量的数据。在函数调用期间,内存的位置不会改变,因为编译器可以优化代码,所以栈数据使用起来也比较快。
  • 堆内存 - 对于在运行时创建的数据。此区域中的数据可以添加、移动、删除、调整大小等。因为它的动态特性,通常认为它使用起来比较慢,但是它允许更多创造性的内存使用。当数据添加到该区域时,我们称其为分配。从本区域中删除数据我们称之为释放

在内存中创建数据

当我们在代码中实例化一个结构体时,我们的程序会在内存中并排创建相关的字段数据。
当我们通过制定所有字段值的方式来实例化时:
结构体 { … };
结构体字段可以通过 . 运算符来获取。

struct SeaCreature {
	animal_type: String,
	name: String,
	arms: i32,
	legs: i32,
	weapon: String,
}

fn main() {
	// SeaCreature 的数据在栈上
	let ferris = SeaCreature {
		// String 结构体也在栈上
		// 但也存放了一个数据在栈上
		animal_type: String::from("螃蟹"),
		name: String::from("Ferris"),
		arms: 2,
		legs: 4,
		weapon: String::from("大钳子"),
	};
	
	let sarah = SeaCreature {
		animal_type: String::from("章鱼"),
		name: String::from("Sarah"),
		arms: 8,
		legs: 0,
		weapon: String::from("无"),
	};
	println!(
	"{} 是只 {}。 它有 {} 只胳膊 {} 只腿。还有一个{}。",
	ferris.name, ferris.animal_type, ferris.arms, ferris.legs, ferris.weapon
	);
	println!(
	"{} 是只 {}。 它有 {} 只胳膊 {} 只腿。它没有杀伤性武器~",
	sarah.name, sarah.animal_type, sarah.arms, sarah.legs
	);
}

这个例子中的内存详情:

  • 引号内的文本数据是只读数据(“例如ferris”),它位于数据内存区
  • 函数调用 String::from 创建一个结构体 String , 该结构体与SeaCreature的字段并排放置在中。字符串容器通过如下步骤表示可更改的文本:
    • 上创建可修改文本的内存。
    • 中存储对象的内存位置的引用存储在 String 结构体中。
  • 最后,我们的两个朋友 Ferris 和 Sarah 是有在程序中总是固定的位置的数据结构,所以它们被放在

类元组结构体

简洁起见,可以创建像元组一样被使用的结构体。

struct Location(i32, i32);

fn main() {
	// 这仍然是一个在栈上的结构体
	let loc = Location(42, 32);
	println!("{}, {}", loc.0, loc.1);
}

类单元结构体

结构体也可以没有任何字段。

就像第一章中提到的, 一个unit是一个空元组()的别称。这就是为什么,此类结构体被称为类单元。

这种类型的结构体很少用到。

struct Marker;

fn main() {
	let _m = Marker;
}

枚举

枚举允许使用 enum 关键字创建一个新类型,该类型的值可以包括几个带标记的元素。

match 有助于确保对多有可能的枚举值进行彻底的处理,使其成为确保高质量代码的强大工具。

#![allow(dead_code)]  // this line prevents compiler warnings

enum Species {
	Crab,
	Octopus,
	Fish,
	Clam
}

struct SeaCreature {
	species: Species,
	name: String,
	arms: i32,
	legs: i32,
	weapon: String,
}

fn main() {
	let ferris = SeaCreature {
		species: Species::Crab,
		name: String::from("Ferris"),
		arms: 2,
		legs: 4,
		weapon: String::from("claw"),
	};
	match ferris.species {
		Species::Crab => println!("{} is a crab.", ferris.name),
		Species::Octopus => println!("{} is a Octopus", ferris.name),
		Species::Fish => println!("{} is a fish", ferris.name),
		Species::Clam => println!("{} is a clam", ferris.name),
	}
}

带数据的枚举

enum 的元素可以有一个或者多个数据类型,从而使其表现得像C语言中的联合。
当使用 match 对另一个 enum 进行模式匹配时,可以将变量名称绑定到每个数据值。

enum 的内存细节:

  • 枚举数据的内存大小等于它最大元素的大小。此举是为了让所有可能的值都能存入相同的内存空间。
  • 除了每个元素数据类型(如果有)之外,每个元素还有个数字值,用于表示他是哪个标签。

其他细节

  • Rust的 enum 也被成为标签联合(tagged-union)
  • 把类型组合成一种新类型,着就是人们所说的Rust具有代数类型的含义。
#![allow(dead_code)]

enum Species { Crab, Octopus, Fish, Clam }
enum PoisonType { Acidic, Painful, Lethal }
enum Size { Big, Small }
enum Weapon {
    Claw(i32, Size),
    Poison(PoisonType),
    None
}

struct SeaCreature {
	species: Species,
	name: String,
	arms: i32,
	legs: i32,
	weapon: Weapon,
}

fn main() {
	// SeaCreature's data is on stack
	let ferris = SeaCreature {
		// String struct is also on stack
		// but holds a reference to data on heap
		species: Species::Crab,
		name: String::from("Ferris"),
		arms: 2,
		legs: 4,
		weapon: Weapon::Claw(2, Size::Small)
	};

	match ferris.species {
		Species::Crab => {
			match ferris.weapon {
				Weapon::Claw(num_claws, size) => {
				let size_description = match size {
					Size::Big => "big",
					Size::Small => "small",
				};
				println!("ferris is a crab with {} {} claws", num_claws, size_description)
                },
                _ => println!("ferris is a crab with some other weapon")
				}
			}
		},
		_ => println!("ferris is some other animal"),
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值