Swift中的结构体
Swift中的结构体是通过struct声明的
- 结构体的初始化
struct YYTeacher {
var age : Int
var name : String
}
对比下面这段class的代码:
class YYTeacher {
var age : Int
var name : String
}
在代码编译过程中,class这段代码会报错:"Class 'YYTeacher' has no initializers"。这是因为Swift编译器在结构体中自动帮助我们合成了初始化方法,而class中需要我们自己定义带有参数的初始化方法。意味着可以这样调用:

这一点也可以通过SIL来查看:

上面是第一种情况:默认初始化没值也没有自定义带参初始化,则编译器自动生成带参初始化。
第二种情况:如果默认初始化有值

第三种情况:如果自己定义了带参初始化方法

- 结构体是值类型
值类型
-
值类型的地址里面存储的就是值 - 传递过程中相当于
copy一个副本(深拷贝)
通过lldb查看:

通过SIL里面也可以看出:
在main中也只是调用了init方法:

在init中也是直接获取地址进行赋值,不参与任何的alloc堆区内存分配`.

引用类型
-
引用类型的地址存储的是一个地址 - 传递过程中相当于
编辑一个在线表格,共享状态(浅拷贝)
下面例子是main.swift中的一个class:
class YYTeacher {
var age : Int = 12
}
var t = YYTeacher()

-
po t: 打印的是t里面存储的东西(值类型则为值,引用类型则为地址)。如果是引用类型,存储的地址则是通过malloc对象在堆区的地址 -
po withUnsafePointer(to: &t){print($0)}:打印的是t自身的地址,t自身在哪里就是哪里的地址
3、值类型和引用类型的区别:就像一个是在线表格,一个是本地的excel,当共享编辑一个在线表格时就相当于一个引用类型;而当通过QQ传一个excel时就相当于一个值类型,不共享状态。
注意:尽可能避免值类型中包含引用类型;虽然放在值类型中,在传递过程中不管是传递还是赋值的操作,对于当前的引用类型还是采用引用计数来管理的。
Mutating
mutating只用于值类型中的方法
struct YYStack {
var items = [Int]()
// _ : 外部参数,可省略
//item : 内部参数,默认let不可变
func push(_ item : Int) {
print(item)
}
}
在上面这个例子中,如果想要在push方法里面修改items或者item,都是编译不通过的。我们可以通过SIL来看一下其中的原因:

值类型self里面存储的就是items,要修改items就是要修改self.
这时要想修改items,就需要在func前面添加关键字mutating.即:
struct YYStack {
var items = [Int]()
mutating func push(_ item : Int) {
items.append(item)
}
}
接下来可以通过SIL看一下mutating到底做了什么:

可以看出:mutating本质上就是给当前值类型添加了一个inout关键字;而inout的本质则是传递过程中传递的是地址(引用)
inout --> 输入输出参数:修饰的是参数类型,所以也可以修饰当前结构体。
