• 首页
        • 更多产品

          客户为中心的产品管理工具

          专业的软件研发项目管理工具

          简单易用的团队知识库管理

          可量化的研发效能度量工具

          测试用例维护与计划执行

          以团队为中心的协作沟通

          研发工作流自动化工具

          账号认证与安全管理工具

          Why PingCode
          为什么选择 PingCode ?

          6000+企业信赖之选,为研发团队降本增效

        • 行业解决方案
          先进制造(即将上线)
        • 解决方案1
        • 解决方案2
  • Jira替代方案
目录

swift中结构体和类的区别(值类型和引用类型的区别)

类是引用类型,存储在堆区;结构体是值类型,存储在栈区。类有继承特性;结构体没有。类实例可以被多次引用,有引用计数。结构体没有引用计数,赋值都是值拷贝。

一、swift中结构体和类的区别

  • 类是引用类型,存储在堆区;结构体是值类型,存储在栈区。
  • 类有继承特性;结构体没有。
  • 类实例可以被多次引用,有引用计数。结构体没有引用计数,赋值都是值拷贝。
  • 类有反初始化器(deinit)来释放资源。
  • 类型转换允许你在运行时检查和解释一个类实例的类型。

值类型 vs 引用类型

结构体是值类型,实际上,Swift 中所有的基本类型:整数,浮点数,布尔量,字符串,数组和字典,还有枚举,都是值类型,并且都以结构体的形式在后台实现。

这意味着字符串,数组和字典在被赋值到一个新的常量或变量,或者它被传递到一个函数或方法中的时候,其实是传递了值的拷贝。这不同于 OC 的 NSString,NSArray 和 NSDictionary,他们是类,属于引用类型,赋值和传递都是引用。

值类型存储的是值,赋值时都是进行值拷贝,相互之间不会影响。而引用类型存储的是对象的内存地址,赋值时拷贝指针,都是指向同一个对象,即同一块内存空间。

1、结构体是值类型

swift

复制代码

struct Book {

    var name: String

    var high: Int

    func turnToPage(page:Int) {

        print(“turn to page \(page)”)

    }

}

var s = Book(name: “程序员的自我修养”, high: 8)

var s1 = s

s1.high = 10

print(s.high, s1.high) // 8 10

这段代码中初始化结构体high为18,赋值给s1时拷贝整个结构体,相当于s1是一个新的结构体,修改s1的high为10后,s的age仍然是8,s和s1互不影响。

通过 lldb 调试, 也能够看出 s 和 s1 是不同的结构体. 一个在 0x100008080, 一个在 0x100008098.

swift

复制代码

(lldb) frame variable -L s

0x0000000100008080: (SwiftTest.Book) s = {

0x0000000100008080:   name = “程序员的自我修养”

0x0000000100008090:   high = 8

}

(lldb) frame variable -L s1

0x0000000100008098: (SwiftTest.Book) s1 = {

0x0000000100008098:   name = “程序员的自我修养”

0x00000001000080a8:   high = 10

}

2、类是引用类型

swift

复制代码

class Person {

    var age: Int = 22

    var name: String?

    init(_ age: Int, _ name: String) {

        self.age = age

        self.name = name

    }

    func eat(food:String) {

        print(“eat \(food)”)

    }

    func jump() {

        print(“jump”)

    }

}

var c = Person(22, “jack”)

var c1 = c

c1.age = 30

print(c.age, c1.age) // 30 30

如果是类,c1=c的时候拷贝指针,产生了一个新的引用,但都指向同一个对象,修改c1的age为30后,c的age也会变成30。

swift

复制代码

(lldb) frame variable -L c

scalar: (SwiftTest.Person) c = 0x0000000100679af0 {

0x0000000100679b00:   age = 30

0x0000000100679b08:   name = “jack”

}

(lldb) frame variable -L c1

scalar: (SwiftTest.Person) c1 = 0x0000000100679af0 {

0x0000000100679b00:   age = 30

0x0000000100679b08:   name = “jack”

}

(lldb) cat address 0x0000000100679af0

address:0x0000000100679af0, (String) $R1 = “0x100679af0 heap pointer, (0x30 bytes), zone: 0x7fff8076a000”

通过lldb调试,发现类的实例 c 和 c1 实际上是同一个对象, 再通过自定义命令 address 可以得出这个对象是在 heap 堆上.

而 c 和 c1 本身是2个不同的指针, 他们里面都存的是 0x0000000100679af0 这个地址.

swift

复制代码

(lldb) po withUnSAFePointer(to: &c, {print($0)})

0x0000000100008298

0 elements

(lldb) po withUnSAFePointer(to: &c1, {print($0)})

0x00000001000082a0

0 elements

延伸阅读:

二、SIL是什么

Swift Intermediate Language,Swift高级中间语言,Swift 编译过程引入SIL有以下优点:

  • 完全保留程序的语义
  • 既能进行代码的生成,又能进行代码分析
  • 处在编译管线的主通道 (hot path)
  • 架起桥梁连接源码与LLVM,减少源码与LLVM之间的抽象鸿沟

SIL会对Swift进行高级别的语意分析和优化。像LLVM IR一样,也具有诸如Module,Function和BasicBlock之类的结构。与LLVM IR不同,它具有更丰富的类型系统,有关循环和错误处理的信息仍然保留,并且虚函数表和类型信息以结构化形式保留。它旨在保留Swift的含义,以实现强大的错误检测,内存管理等高级优化。

相关文章