简介
结构体(struct)是由一系列具有相同类型或不同类型的数据构成的数据集合,可以定义属性(存储属性,可以是常量、变量)和添加方法。
结构体是值类型
在 Swift 标准库中,绝大多数的公开类型都是结构体,比如Bool、Int、Double、 String、Array、Dictionary 等常见类型都是结构体。
语法
定义
通过关键字 struct 来定义结构体:
struct nameStruct {
def 1
def 2
...
method 1
method 2
...
}
示例:Time 结构体,定义了三个存储属性和一个方法
struct Time {
var hour: Int
var minute: Int
var second: Int
func showTime() {
print("\(hour):\(minute):\(second)")
}
}
使用
所有的结构体都有一个编译器自动生成的初始化器(initializer,初始化方法、构造器、构造方法) ,编译器会根据情况,可能会为结构体生成多个初始化器,宗旨是:保证所有成员都有初始值。
当定义结构体时,如果其中的属性没有初始化,则在初始化结构体时,没初始化过的属性为必传参数。
例如上面的 Time 结构体,定义中没有初始化 hour、minute、second,则在调用结构体初始化器的时候,三个参数均为必传参数,否则异常:
当将 minute、second 定义时初始化赋值,则在调用结构体初始化器时,hour 必传,minute、second 可选,因此 time0、time1、time2 是正确的,time3 异常
上面调用的是结构体自动生成的初始化构造器,同样我们也可以自定义初始化器。
当然,一旦我们自定义了初始化器,,编译器就不会再帮它自动生成其它的初始化器。
同样的原则:自定义的初始化器,也要能确保所有成员都有初始值,否则异常。
如:
自定义初始化器,保证 hour 能被初始化:
struct Time {
var hour: Int
var minute: Int = 0
var second: Int = 0
init(h: Int, m: Int, s: Int) {
self.hour = h
self.minute = m
self.second = s
}
func showTime() {
print("\(hour):\(minute):\(second)")
}
}
var time3 = Time(h: 23, m: 59, s: 59);
初始化器的本质
struct Time {
var hour: Int = 23
var minute: Int = 59
var second: Int = 59
}
var time = Time()
等价于:
struct Time {
var hour: Int
var minute: Int
var second: Int
init() {
hour = 23
minute = 59
second = 59
}
}
var time = Time()
分别 debug 调试,上面两种情况的汇编代码是一模一样的
结构体内存布局
结构体实际使用内存为结构体各成员字节长度之和,当然实际分配的内存还需根据内存对齐参数值得到。
struct Time {
var hour: Int = 23
var minute: Int = 59
var second: Int = 59
}
print("实际使用: ",MemoryLayout<Time>.size)
print("实际分配: ",MemoryLayout<Time>.stride)
print("对齐值: ",MemoryLayout<Time>.alignment)
控制台打印信息:
实际使用: 24
实际分配: 24
对齐值: 8
结构体类型为值类型:
struct Time {
var hour: Int = 23
var minute: Int = 59
var second: Int = 59
}
var time1 = Time()
print("赋值前time1-\(time1.hour):\(time1.minute):\(time1.second)")
var time2 = time1
time2.minute = 23
time2.second = 23
print("赋值并变更后time1-\(time1.hour):\(time1.minute):\(time1.second)")
print("赋值并变更后time2-\(time2.hour):\(time2.minute):\(time2.second)")
输出信息:
赋值前time1-23:59:59
赋值并变更后time1-23:59:59
赋值并变更后time2-23:23:23
可以看到当将 time1 直接赋值给 time2 后,修改 time2,并不会对 time1 产生影响。