结构体基础
本教程共 93 篇 · 第 51 篇 · 更新于 2026-08-08 · 约 8 分钟阅读
本节目标:读完你能用 struct 定义自己的类型,理解结构体是值类型、赋值时会被拷贝,并会用成员逐一初始化器创建实例。
1-1 结构体是什么
结构体(struct)是 Swift 里最基础的自定义类型之一。它把一组相关的属性和功能打包成一个整体。和枚举一样,结构体也是值类型。日常很多 Swift 类型(String、Int、Array、Dictionary)背后都是结构体,只是你平时没察觉。
你可以把结构体想成一个”自制的盒子”,盒子上贴着类型名,里面分格装着各种属性。比起散落各处的变量,盒子让相关数据聚在一起,更好管理,也更不容易传错参数。
1-2 定义结构体
用 struct 关键字,属性写在花括号内,命名用大驼峰,属性名用小驼峰:
struct Resolution {
var width = 0
var height = 0
}
width、height 是存储属性,初始值 0 让 Swift 推断出它们是 Int。属性可以是 var(可变)也可以是 let(不可变),根据你希望它能不能改来决定。
1-3 创建实例
创建实例用”初始化器语法”:类型名加空括号(若属性有默认值)或传参:
let someResolution = Resolution()
结构体有一个类没有的特权:自动获得”成员逐一初始化器”(memberwise initializer),可以按属性名传值:
let vga = Resolution(width: 640, height: 480)
类没有这个自动初始化器,得自己写。这是结构体省心的一大原因。成员逐一初始化器的参数顺序,和属性在结构体里声明的顺序一致,名字就是属性名,调用时非常直观。
1-4 访问与修改属性
用点语法读、改属性:
print("宽度是 \(someResolution.width)")
var cinema = vga
cinema.width = 2048
print("cinema 现在 \(cinema.width)") // 2048
print("vga 仍是 \(vga.width)") // 640
点语法不仅能访问一层,还能连着往下钻:如果某个属性本身又是个结构体,可以继续用点取到它的子属性,写起来像 a.b.c。
1-5 值类型:赋值是拷贝
关键点来了:结构体是值类型。把 vga 赋给 cinema 时,Swift 复制了一份,两者从此是独立的实例。改 cinema 不影响 vga。这就是”值类型”的含义——传来传去的是值的副本。
Warning把结构体实例赋给 let 常量后,哪怕属性声明是 var,也不能改。因为常量结构体的所有属性都随它一起变成只读。这是初学者常漏的一点。
标准库的集合类型(数组、字典、字符串)用”写时复制”优化性能:没真正修改前共享同一份内存,一旦修改才复制。你写代码时看到的行为,始终等价于”立刻拷贝”。所以你可以放心地认为:结构体赋值时,两边互不影响。
1-6 何时用结构体
苹果官方建议:默认用结构体。它更容易推理——因为每次传递都是拷贝,相关代码集中在一处,不会有”别处偷偷改了它”的意外。需要继承、引用语义、生命周期管理时才用类。绝大多数自定义类型用 struct 就够了。
1-7 和枚举的共通之处
结构体与枚举都是值类型,也都可以在内部定义方法、计算属性、遵循协议。区别在于:枚举适合”有限几种互斥状态”,结构体适合”一组相关数据组成一个整体”。选哪个,看你的数据更像”菜单里挑一个”还是”把几样东西装一盒”。
1-8 结构体的属性默认值和推断
定义属性时给它一个初值(如 var width = 0),Swift 就能推断出类型,并自动把这个值作为默认。若属性没有初值,结构体就不会有默认初始化器,你必须自己写。想让外部传值,就别给默认,或显式声明类型并写初始化器。理解”默认值从哪来”,能避免很多初始化报错。
成员逐一初始化器的参数,正是按”没有默认值的属性”来要求的。所以一个实用技巧是:给所有属性都设默认值,就能白嫖一个无参初始化器;只想让调用方传部分值,就只给其余属性默认值。
1-9 值类型与函数参数
把结构体当函数参数传进去时,也是拷贝。函数内部改了它,外面不受影响——除非参数标了 inout(那另说)。这点对调试很友好:你不用怀疑”是不是别的调用改了我的结构体”,因为只要没用 inout、没逃逸,它就在自己的作用域里独立存在。
这也解释了为什么 Swift 鼓励多用结构体:并发场景下,值类型不会被多个地方同时修改,天然少了很多数据竞争的隐患。虽然本教程不展开并发,但记住”值类型更易推理”这个好处就够了。
1-10 结构体也能遵循协议
虽然协议要后面才正式讲,但先说一句:结构体可以遵循协议,从而获得统一的行为约定。比如让多个结构体都遵循同一个”可描述”协议,就能用同一套方式打印它们。Swift 的很多能力(如遍历、比较、哈希)都是通过协议赋给结构体的。
这也解释了为什么结构体不只是”装数据的盒子”——它同样能拥有行为、能融入 Swift 的类型体系。理解到这一层,你就明白为什么苹果说”优先用结构体”了。
1-11 结构体是 Swift 的默认选择
回到一开始的建议:苹果官方明确说”优先用结构体”。原因我们已经拆解完——值类型易推理、默认带初始化器、拷贝语义避免意外共享。当你犹豫”用 struct 还是 class”时,先假设用结构体,只有当确实需要继承、引用语义或显式生命周期管理时,才换成类。这个默认能帮你避开很多面向对象里常见的坑。
1-12 小结
结构体用 struct 定义,属性与方法打包成类型。它自动带成员逐一初始化器,类没有。结构体是值类型,赋值即拷贝,互不干扰;常量结构体整体只读。优先用结构体,是 Swift 的通用准则。下章看结构体的属性和方法。