美文网首页
Swift 类和结构体底层探究

Swift 类和结构体底层探究

作者: 一粒咸瓜子 | 来源:发表于2022-06-29 14:08 被阅读0次

    总结

    结构体是值类型,存放在栈空间中
    类是引用类型,指针存放在栈空间,指向堆空间。


    针对 64bit 环境:
    在 Point 中 一个 Int 占8个字节
    0x90000 指针在栈中占用8个字节,指向 Size 在堆中的地址,占用32个字节,其中前2个8字节有特殊的用处,第一个存放指向类型的信息,第二个是引用计数。

    结构体是值类型

    值类型赋值给 var、let或者给函数传参,是直接将所有的内容拷贝一份。
    类似于对文件进行copy,产生了全新的文件副本。属于深拷贝。


    从反编译的结果来看,p2 = p1 实际上是开辟了新的内存地址,证实是深拷贝,所以修改 p2 的值不会影响 p1。

    类是引用类型

    引用赋值给 var let 或者给函数传参,是将内存地址拷贝一份
    类似于制作一个文件的替身(快捷方式、链接),指向的是同一个文件。属于浅拷贝。

    对象的堆空间申请过程

    在MAC、iOS中的malloc函数分配的内存大小总是16的倍数

    在Swift中,创建类的实例对象,要向堆控件申请内存,大概流程如下:
    Class.__allocating_init()
    libswiftCore.dylib: \_swift_allocObject
    libswiftCore.dylib: swift_slowAlloc
    libsystem_malloc.dylib: malloc

    通过class_getInstanceSize可以得知:类的对象至少需要占用多少内存

    赋值过程

    找到初始化函数,返回值一般存于 rax 中,类的初始化方法返回值应为申请堆空间的地址


    register read rax 找到堆空间地址,在 View Memery 中查看内存分配情况


    第1个8位存的是指向类型信息,第2个8位存的是引用计数信息,之后2个8位存的是初始值10,11

    之后找立即数12,13 也就是找$0xc,$0xd



    能看出分别是存于 rax+0x10 和 rax+0x18,能推出分别对应 s2.width、s2.height,均是 rax 为地址的第一位,所以得出结论 s1 和 s2存的是同一份地址。

    值与引用类型的 let

    p = Point(x:3, y:4)
    p.x = 10 p.y = 10

    • 错误的原因为 p 是值类型,p 的内存占16个字节,存储 x,y
      let 代表这16个字节的内容无法变更。

    s = Size(20, 21)

    • 错误的原因为 s 是引用类型常量,存储的是指向堆空间的指针
      let 代表这个指针无法变更。

    s.width = 20 s.height = 20

    • 正确的原因是,修改的是指针所指向的堆空间内容,可以变更

    相关文章

      网友评论

          本文标题:Swift 类和结构体底层探究

          本文链接:https://www.haomeiwen.com/subject/tgiavrtx.html