//寫法一
class PDTeacher {
var age:Int
func teach() {
print("teach")
}
init(_ age: Int) {
self.age = age
}
}
var t = PDTeacher.init(20)
//寫法二
class PDTeacher2 {
var age:Int?;
func teach() {
print("teach")
}
init(_ age: Int) {
self.age = age
}
}
var t1 = PDTeacher2.init(12)
複製代碼
init
方法定義一個類,經過一個例子說明數組
class CJLTeacher1 {
var age: Int = 18
var age2: Int = 20
}
var t1 = CJLTeacher1()
複製代碼
類初始化的對象t1,存儲在全局區markdown
po t1
,從圖中能夠看出,t1
內存空間中存放的是地址
,t
中存儲的是值
po withUnsafePointer(to: &t1){print($0)}
x/8g 0x0000000100008218
x/8g 0x00000001040088f0
堆區地址
堆區地址
中存儲的是值
lldb
調試得知,修改了t2
,會致使t1
改變,主要是由於t2
、t1
地址中都存儲的是 同一個堆區地址
,若是修改,修改是同一個堆區地址,因此修改t2會致使t1一塊兒修改,即淺拷貝
代碼以下所示app
class CJLTeacher1 {
var age: Int = 18
var age2: Int = 20
}
struct CJLTeacher {
var age: Int = 18
var age2: Int = 20
var teacher: CJLTeacher1 = CJLTeacher1()
}
var t = CJLTeacher()
var t1 = t
t1.teacher.age = 30
//分別打印t1和t中teacher.age,結果以下
t1.teacher.age = 30
t.teacher.age = 30
複製代碼
從打印結果中能夠看出,若是修改t1中的實例對象屬性,會致使t中實例對象屬性的改變。雖然在結構體中是值傳遞
,可是對於teacher,因爲是引用類型
,因此傳遞
的依然是地址
函數
一樣能夠經過lldb調試驗證spa
po withUnsafePointer(to: &t){print($0)}
x/8g 0x0000000100008238
x/8g 0x000000010070e4a0
注意 在編寫代碼過程當中,應該儘可能
避免值類型包含引用類型
3d
查看當前的SIL文件,儘管CJLTeacher1是放在值類型中的,在傳遞的過程當中,不論是傳遞仍是賦值,teacher都是按照引用計數進行管理的 能夠經過打印teacher的引用計數來驗證咱們的說法,其中teacher的引用計數爲3
指針
主要是是由於:調試
main
中retain
一次excel
teacher.getter
方法中retain
一次code
teacher.setter
方法中retain
一次
經過結構體
定義一個棧
,主要有push
、pop
方法,此時咱們須要動態修改棧中的數組
值類型自己是不容許修改屬性
的struct CJLStack {
var items: [Int] = []
func push(_ item: Int){
print(item)
}
}
複製代碼
從圖中能夠看出,push函數除了item,還有一個默認參數self,
self是let類型
,表示不容許修改
struct CJLStack {
var items: [Int] = []
func push(_ item: Int){
var s = self
s.items.append(item)
}
}
複製代碼
打印結果以下 能夠得出上面的代碼並不能將item添加進去,由於s是另外一個結構體對象,至關於值拷貝,此時調用push是將item添加到s的數組中了
struct CJLStack {
var items: [Int] = []
mutating func push(_ item: Int){
items.append(item)
}
}
複製代碼
查看其SIL
文件,找到push函數,發現與以前有所不一樣,push添加mutating(只用於值類型)後,本質上是給值類型函數添加了inout關鍵字
,至關於在值傳遞的過程當中,傳遞的是引用(即地址)
都是不可變
的,若是想要直接修改,須要給參數加上inout
關鍵字inout
關鍵字,給參數賦值,編譯報錯inout
關鍵字,能夠給參數賦值一、結構體中的函數若是想修改其中的屬性,須要在函數前加上mutating,而類則不用
二、mutating本質也是加一個 inout修飾的self
三、Inout至關於取地址,能夠理解爲地址傳遞,即引用
四、mutating修飾方法,而inout 修飾參數
經過上述LLDB查看結構體 & 類的內存模型,有如下總結:
值類型,至關於一個本地excel,當咱們經過QQ傳給你一個excel時,就至關於一個值類型,你修改了什麼咱們這邊是不知道的
引用類型,至關於一個在線表格,當咱們和你共同編輯一個在先表格時,就至關於一個引用類型,兩邊都會看到修改的內容
結構體中函數修改屬性, 須要在函數前添加mutating關鍵字,本質是給函數的默認參數self添加了inout關鍵字,將self從let常量改爲了var變量