之前我们介绍过Swift中class与Struct的区别,他们的本质区别其实就是类型的区别.(类是引用类型,结构体是值类型),下面我们仔细介绍一下引用类型与值类型.
首先,我们知道内存(RAM)中有两个区域,栈区(stack)和堆区(heap).
在 Swift 中,引用类型,存放在堆区;值类型,存放在栈区。(关于堆栈https://www.jianshu.com/p/924eaf8ffac4)
通过代码测试可知:
- 引用类型,即所有实例共享一份数据拷贝。(浅拷贝-影子)
- 值类型,即每个实例保持一份数据拷贝。(深拷贝-克隆人)
浅拷贝就是你的影子,深拷贝是你的克隆人
引用类型
import UIKit
print("class=======")
class TestClass{
var a : Int = 0
var b : String = ""
}
var t = TestClass()
var t1 = t
t1.a = 5
print(t.a)//5
print(t1.a)//5
//在 Swift 中,可以使用以下方法来打印引用类型变量指向的内存地址。从中即可发现,两个变量指向的是同一块内存空间
print("变量t内存地址----\(Unmanaged.passUnretained(t).toOpaque())")//变量t内存地址----0x0000600001f8e4f0
print("变量t1内存地址----\(Unmanaged.passUnretained(t1).toOpaque())")//变量t1内存地址----0x0000600001f8e4f0
//在 Swift 中,三等号(=== & !==)可以用来比较引用类型的引用(即指向的内存地址)是否一致。也可以在遵守 Equatable 协议后,使用双等号(== & !=)用来比较变量的内容是否一致。
print("===比较变量内存地址----\(t==t1)")//===比较变量内存地址----true
extension TestClass: Equatable {
static func ==(left: TestClass, right: TestClass) -> Bool {
return (left.a == right.a && left.b == right.b)
}
}
print("==比较变量存储的内容----\(t==t1)")// ===比较变量内存地址----true
引用类型堆栈.png
值类型
print("struct=======")
struct TestStruct{
var a : Int = 0
var b : String = ""
}
var s = TestStruct(a: 0)
var s1 = s
s1.a = 5
print(s.a)//0
print(s1.a)//5
//在 Swift 中,可以使用 withUnsafePointer(to:_:) 函数来打印值类型变量的内存地址,这样就能看出两个变量的内存地址并不相同。
withUnsafePointer(to: &s) {
print("变量s内存地址----\($0)")//变量s内存地址----0x000000011f285910
}
withUnsafePointer(to: &s1) {
print("变量s1内存地址----\($0)")//变量s1内存地址----0x000000011f285928
}
//在 Swift 中,双等号(== & !=)可以用来比较变量存储的内容是否一致,如果要让我们的 struct 类型支持该符号,则必须遵守 Equatable 协议。
extension TestStruct: Equatable {
static func ==(left: TestStruct, right: TestStruct) -> Bool {
return (left.a == right.a && left.b == right.b)
}
}
print("==比较变量存储的内容----\(s==s1)")//==比较变量存储的内容----false
值类型堆栈.png
网友评论