Swift中的结构体、值类型和引用类型

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 --> 输入输出参数:修饰的是参数类型,所以也可以修饰当前结构体

你可能感兴趣的:(Swift中的结构体、值类型和引用类型)