討論之前,先復習下 概念:Value Type(值類型),Reference Type(引用類型):
值類型:值類型的變量直接包含他們的數據,對于值類型都有他們自己的數據副本,因此對一個變量操作不可能影響另一個變量;
引用類型:引用類型的變量存儲對他們的數據引用,因此后者稱為對象,因此對一個變量操作可能影響另一個變量所引用的對象。
深拷貝與淺拷貝: 深拷貝就是內容拷貝,淺拷貝就是指針拷貝
1. 是否開啟新的內存地址
2. 是否影響內存地址的引用計數
開始Struct與Class,創建一個Struct:【SPeople】 與 Class:【CPeople】
1 struct SPeople 2 3 { 4 var age: Int? 5 } 6 7 class CPeople 8 { 9 var age: Int? 10 }
1、property初始化的不同:
1 let speople = SPeople(age: 4) // struct可直接在構造函數中初始化property 2 print("speople.age:\(String(describing: speople.age))") 3 4 let cpeople = CPeople() // class不可直接在構造函數中初始化property
5 cpeople.age = 5 print("cpeople.data:\(String(describing: cpeople.age))")
打印結果:
1 speople.data:Optional(4) 2 cpeople.data:Optional(5)
主要的差別就是 class 在初始化時不能直接把 property 放在 默認的constructor 的參數里,而是需要自己創建一個帶參數的constructor, 如:
class CPeople {
var age: Int?
init(data: Int) {
self.age = age
}
}
let cnode = CPeople.init(age: 5)
2、變量賦值方式不同(深淺copy)
// struct
let speople = SPeople(age: 18)
var speople1 = speople
speople1.age = 19
print("speople.age:\(String(describing: speople.age))\n speople.age:\(String(describing: speople1.age))")
打印結果:
speople.age:Optional(18) speople.age:Optional(19)
說明:struct 賦值“=”的時候,會copy一份完整相同的內容給另一個變量 --> 【開辟了新的內存地址】
// class
let people = CPeople()
people.age = 5
let people1 = people
people1.age = 6
print("cpeople.age:\(String(describing: cpeople.age))\n cpeople1.age:\(String(describing: cpeople.age))")
打印結果:
cpeople.age:6 cpeople1.age:6
說明:class 賦值“=”的時候,不會copy一份完整的內容給另一個變量,只是增加了原變量內存地址的引用而已 --> 【沒有開辟了新的內存地址】
3、immutable 變量
Swift 語言的特色之一就是可變動內容和不可變內容用 var 和 let 來甄別,如果初始為let的變量再去修改會發生編譯錯誤。
struct也遵循這一特性
class不存在這樣的問題:從上面的賦值代碼能很清楚的看出來。
4、mutating function
struct SPeople {
var age: Int
}
extension SPeople {
mutating func changeAge(vaule: Int) {
self.age = vaule
}
}
class CPeople {
var Data: Int = 0
}
extension CPeople {
func changeAge(vaule: Int) {
self.Age = vaule
}
}
說明:struct 和 class 的差別是 struct 的 function 要去改變 property 的值的時候要加上 mutating,而 class 不用。
5、繼承
struct不能繼承,class可以繼承。
6、struct比class更“輕量級”
struct分配在棧中,class分配在堆中。
題外話:Swift 把 Struct 作為數據模型的注意事項
優點:
1、安全性:
因為 Struct 是用值類型傳遞的,它們沒有引用計數。
2、內存:
由于他們沒有引用數,他們不會因為循環引用導致內存泄漏。
3、速度:
值類型通常來說是以棧的形式分配的,而不是用堆。因此他們比 Class 要快很多! (http://stackoverflow.com/a/24243626/596821)
4、拷貝:
Objective-C 里拷貝一個對象,你必須選用正確的拷貝類型(深拷貝、淺拷貝),而值類型的拷貝則非常輕松!
5、線程安全
值類型是自動線程安全的。無論你從哪個線程去訪問你的 Struct ,都非常簡單。
缺點:
1、Objective-C
當你的項目的代碼是 Swift 和 Objective-C 混合開發時,你會發現在 Objective-C 的代碼里無法調用 Swift 的 Struct。因為要在 Objective-C 里調用 Swift 代碼的話,對象需要繼承于 NSObject。
Struct 不是 Objective-C 的好朋友。
2、繼承
Struct 不能相互繼承。
3、NSUserDefaults
Struct 不能被序列化成 NSData 對象。
所以:如果模型較小,并且無需繼承、無需儲存到 NSUserDefault 或者無需 Objective-C 使用時,建議使用 Struct。
知識延伸:為什么訪問struct比class快?
“堆”和“棧”并不是數據結構上的Heap跟Stack,而是程序運行中的不同內存空間。棧是程序啟動的時候,系統事先分配的,使用過程中,系統不干預;堆是用的時候才向系統申請的,用完了需要交還,這個申請和交還的過程開銷相對就比較大了。
棧是編譯時分配空間,而堆是動態分配(運行時分配空間),所以棧的速度快。
從兩方面來考慮:
1.分配和釋放:堆在分配和釋放時都要調用函數(MALLOC,FREE),比如分配時會到堆空間去尋找足夠大小的空間(因為多次分配釋放后會造成空洞),這些都會花費一定的時間,而棧卻不需要這些。
2.訪問時間:訪問堆的一個具體單元,需要兩次訪問內存,第一次得取得指針,第二次才是真正得數據,而棧只需訪問一次。

浙公網安備 33010602011771號