基于本文回答

播面 播面

刷题像听歌,多听自然懂
0
评论

Swift中的值类型 (Value Type) 和 引用类型 (Reference Type)

知识点图片

在 Swift 中,理解 值类型 (Value Type)引用类型 (Reference Type) 的区别是掌握这门语言的核心。它们决定了数据如何在内存中存储、传递以及被修改。

简单总结:

  • 值类型复制 (Copy)。当你传递它时,你得到的是一份副本。
  • 引用类型共享 (Share)。当你传递它时,你得到的是指向同一个实例的指针。

1. 值类型 (Value Types)

在 Swift 中,值类型的数据在赋值给变量、常量,或者传递给函数时,会进行复制。修改副本不会影响原始数据。

包含哪些?

  • 结构体 (struct)
  • 枚举 (enum)
  • 元组 (tuple)
  • 基本数据类型 (其实都是结构体):Int, Double, Bool, String, Array, Dictionary, Set

代码示例:

plaintext
struct SPoint {
    var x = 0.0
    var y = 0.0
}

var pointA = SPoint(x: 10, y: 10)
var pointB = pointA // 这里发生了复制,pointB 是一个新的实例

pointB.x = 20 // 修改 pointB

print(pointA.x) // 输出: 10.0 (原始数据未变)
print(pointB.x) // 输出: 20.0 (副本已变)

特点:

  • 线程安全:因为每个线程都有自己的副本,不需要担心多线程竞争问题。
  • 内存存储:通常存储在栈 (Stack) 上(除非它们是类的一部分),分配和释放速度非常快。
  • 无继承:结构体和枚举不支持继承。

2. 引用类型 (Reference Types)

引用类型的数据在赋值或传递时,不会复制数据本身,而是传递内存地址的引用(指针)。多个变量可能指向内存中的同一个实例。修改其中一个,所有指向该实例的变量都会受到影响。

包含哪些?

  • 类 (class)
  • 闭包 (closure)
  • Actor (actor) (Swift 5.5+)

代码示例:

plaintext
class CPoint {
    var x = 0.0
    var y = 0.0
    init(x: Double, y: Double) { self.x = x; self.y = y }
}

var refA = CPoint(x: 10, y: 10)
var refB = refA // 这里传递的是引用,refA 和 refB 指向同一个对象

refB.x = 20 // 修改 refB 指向的对象

print(refA.x) // 输出: 20.0 (原始数据也被改变了!)
print(refB.x) // 输出: 20.0

特点:

  • 共享状态:适用于需要管理共享数据的情况(如数据库连接、文件句柄)。
  • 内存存储:存储在堆 (Heap) 上,内存管理较复杂。
  • ARC 管理:Swift 使用自动引用计数 (ARC) 来管理其生命周期。
  • 支持继承:类支持继承。

3. 核心区别深度对比

A. 可变性 (Mutability) 与 let

这是 Swift 中最显著的区别之一。

  • 值类型:如果你用 let 声明一个结构体实例,那么该实例及其所有属性都是不可变的,即使属性本身被声明为 var

    plaintext
    struct Person { var name: String }
    let p = Person(name: "Alice")
    // p.name = "Bob" // ❌ 报错!因为 p 是 let,且 Person 是值类型
  • 引用类型:如果你用 let 声明一个类实例,你只是不能改变引用指向(不能把变量指向另一个对象),但你可以修改对象内部的属性

    plaintext
    class Student { var name: String; init(name: String){ self.name = name } }
    let s = Student(name: "Alice")
    s.name = "Bob" // ✅ 允许!因为 s 指向的对象内部是可以变的
    // s = Student(name: "Charlie") // ❌ 报错!不能改变 s 的指向

B. 判等 (Identity)

  • 值类型使用 ==:比较两个实例的内容是否相等(需要遵守 Equatable 协议)。
  • 引用类型使用 ===:比较两个变量是否指向内存中的同一个地址(Identity)。

C. 内存管理 (Stack vs Heap)

  • 值类型 (Stack):类似于把盘子一个个叠起来。存取速度极快,由系统自动弹出,不需要复杂的管理。
  • 引用类型 (Heap):类似于在一个杂乱的房间里找空地放东西。分配内存需要搜索空闲块,释放内存需要 ARC 追踪引用计数,开销相对较大。

4. 特殊机制:写时复制 (Copy-on-Write, COW)

你可能会担心

00:00
00:00