第 5 章 函数与结构体
在前两章中,我们拆解了语言内置与标准库提供的核心类型构造器(引用、数组、切片、Vec<T> 与字符串)。从这一章开始,我们进入自定义类型与业务建模——看如何定义自己的函数与复合数据结构。
习惯了面向对象语言(如 Java 或 C++)的开发者,在初次接触 Rust 的函数和结构体时,往往会遇到三个直观的差异:
- 为什么 Rust 没有
void关键字,而且函数最后一行多打一个分号;就会导致编译报错? - 为什么定义一个
struct只有光秃秃的字段,既没有对象头,默认也不能按位复制(Copy),甚或把其中一个字段移走后,剩下的字段还能继续单独访问? - 为什么 Rust 的方法没有隐式的
this指针,而是必须在第一个参数位置显式写出&self、&mut self或self?
这一章分三步把「函数、结构体与方法」的底层机制串成闭环:
- 第一步:函数、元组与表达式控制流——确立函数签名作为跨函数类型与所有权校验边界的地位;看清空元组
()(单元类型,占 0 字节)如何统一取代void,理解末尾分号;如何把产出值的表达式变成返回()的语句,以及为什么if / else和代码块{}本身都能算出确定类型的值。 - 第二步:结构体(
struct)与部分移动(Partial Move)——掌握具名字段结构体、元组结构体与 0 字节单元结构体的定义与扁平内联内存布局;理解为什么自定义结构体默认一律走移动语义(需显式标注#[derive(Clone, Copy)]),并拆解移出单个字段后编译器在字段粒度上的部分移动追踪规则。 - 第三步:方法接收者三件套与调用点自动解引用——通过
impl块将行为挂载到类型上,区分关联函数(::)与方法(.);看清&self、&mut self、self如何直接对应只读借用、独占可变借用与所有权消费,以及编译器在.调用点自动补齐&、&mut与*的规则与安全边界。
读完这一章,你应该能够回答以下三个问题:
- 表达式与语句的分界:函数体或
if / else分支末尾加不加分号;,对求值产出的类型有什么影响? - 字段级的所有权状态:当结构体中的某个非
Copy字段被移走后,原结构体变量整体、被移走的字段以及其余未移动的字段分别处于什么可用状态? - 方法接收者如何选型:在设计结构体方法或审查代码时,什么时候用
&self、什么时候用&mut self、什么时候应该用按值消费的self?