Swfit 屬性與彙編分析inout本質
- 2020 年 3 月 9 日
- 筆記
今天將講述Swift屬性以及剖析inout的本質, 如有興趣可點擊關注,以後會定期更新更有料的博客!!!
一、屬性
Swift中跟實例相關的屬性可以分為2大類
- 存儲屬性(Stored property)
- 類似於成員變量這個概念
- 存儲在實例的內存中
- 結構體、類可以定義存儲屬性
- 枚舉不可以定義存儲屬性
2. 計算屬性(Computed Property)
- 本質就是方法(函數)
- 不佔用實例的內存
- 枚舉、結構體、類都可以定義計算屬性
struct Circle { //存儲屬性 var radius: Double //計算屬性 var diameter: Double { set{ radius = newValue / 2 } get{ radius * 2 } } }
1. 存儲屬性
將針對例子講解上面的結論
將結構體Struct改為類Class,如下
解釋下為什麼枚舉Enum不可以定義存儲屬性?
2. 計算屬性
上面說到計算屬性相當於函數方法的意思如下,前後兩者完全等價
總結
存儲屬性: 關於存儲屬性,Swift有個明確的規定
- 創建類或者結構體時, 必須為所有的存儲屬性設置一個合適的初始值
- 可以在初始化器內為存儲屬性設置一個初始值,也可以分配一個默認的屬性值作為屬性定義的一部分
計算屬性: set傳入的新值默認為newValue,也可以自定義
- 只讀計算屬性: 只有get,沒有set
- 可讀可寫屬性
- 沒有隻寫屬性,單獨一個set方法是不可以的
枚舉的原始值rawValue的本質是只讀計算屬性
3. 延遲存儲屬性(Lazy Stored Property)
使用lazy可以定義一個延遲存儲屬性, 在第一次用到屬性的時候才會進行初始化
4. 屬性觀察器(Property Observer)
可以為非lazy的var存儲屬性設置屬性觀察器,也是存儲屬性
注意: 在初始化器中設置屬性值不會觸發willSet和didSet方法!!!
二、inout本質
inout:輸入輸出參數的本質就是引用傳遞(地址傳遞)
通過inout查看彙編代碼:leap命令: 將地址傳入進去
inout本質總結:
如果實參有物理內存地址且沒有設置屬性觀察器:直接將實參的內存地址傳入函數(實參進行引用傳遞)
如果實參是計算屬性 或者 設置了屬性觀測器:採取了蘋果官方說的 Copy In Copy Out的做法
- 調用該函數時,先複製實參的值,產生局部變量副本(相當於get)
- 將副本的內存地址傳入函數(副本進行引用傳遞),在函數內部可以修改副本的值
- 函數返回後,再將副本的值覆蓋實參的值