指針
為什么說指針不安全
1)比如我們在創(chuàng)建一個對象的時候殊霞,是需要在堆分配內(nèi)存空間的。但是這個內(nèi)存空間的聲明周期是有限的暂题,也就意味著如果我們使用指針指向這塊內(nèi)容空間啥纸,如果當(dāng)前內(nèi)存空間的生命周期到了(引用計數(shù)為0),那么我們當(dāng)前的指針是不是就變成了未定義的行為了誓斥。
2)我們創(chuàng)建的內(nèi)存空間是有邊界的只洒,比如我們創(chuàng)建一個大小為10的數(shù)組,這個時候我們通過指針訪問到了index = 11的位置劳坑,這個時候是不是就越界了毕谴,訪問了一個未知的內(nèi)存空間。
3)指針類型與內(nèi)存的值類型不一致距芬,也是不安全的墓拜。
Swift里的指針類型
Swift中的指針分為兩類球订,typed pointer指定數(shù)據(jù)類型指針给赞,raw pointer未指定數(shù)據(jù)類型的指針(原生指針)砾跃。基本上我們接觸到的指針類型有以下幾種:
泛型指針的使用
這里的泛型指針相比較原生指針來說离斩,其實就是指定當(dāng)前指針已經(jīng)綁定到了具體的類型银舱。在進行泛型指針訪問的過程中瘪匿,我們并不是使用load和store方法來進行存儲操作,這里我們使用到當(dāng)前泛型指針內(nèi)置的變量pointee寻馏。
還有一種方式就是直接分配內(nèi)存
Swift與OC里的不同的是棋弥,直接定義指針存儲的類型(這里用存的是LGStruct類型),其中通過allocate去創(chuàng)建操软,然后通過deallocate()去釋放嘁锯。
內(nèi)存綁定
Swift提供了三種不同的API來綁定/重新綁定指針:
1)assumingMemoryBound(to:)
2)bindMemory(to:capacity:)
3)withMemoryRebound(to:capacity:body:)(臨時改變內(nèi)存綁定)
下面是用assumingMemoryBound來的:這個是告知編譯器我當(dāng)前是Int類型,不需要額外進行檢查聂薪,直接使用家乘。
內(nèi)存管理
swift中使用自動引用計數(shù)(ARC)機制來追蹤和管理內(nèi)存。
首先我們先找到 RefCount 的定義藏澳,這里我們在HeapObject.h文件中
在源碼里通過分析仁锯,可以得到引用計數(shù)是存放中RefcountBitsInt里,這個是一個64bit的位 域計數(shù)翔悠,下面是各個地址存儲的信息业崖。
下面是對應(yīng)的swift里的引用計數(shù)的代碼,使用了swift_retain函數(shù)蓄愁,進行refCounts的增加双炕。
下面這段代碼就產(chǎn)生了兩個實例對象強引用,swift提供了兩種辦法用來解決使用類的屬性時所遇到的循環(huán)強引用問題撮抓,弱引用(weak reference )和無主引用(unowned reference)妇斤。
聲明一個weak變量相當(dāng)于定義了一個weakrefrence對象
同時在swift里的引用計數(shù)用到了sideTable來存儲:
Swift中存在兩種引用計數(shù),一種是inlineRefCount是丹拯,一種是SideTableRefCounts站超。Side Table是一種類名為
HeapObjectSizeTableEntry的結(jié)構(gòu),里面也有RefCounts成員乖酬,是內(nèi)部是SizeTableRefCountBits死相,其實就是原來的uint64_t加上一個存儲弱引用數(shù)的uint32_t。
這里我們來總結(jié)一下我們當(dāng)前的引用計數(shù)咬像,一個對象在初始化的時候后是沒有SizeTable的算撮,當(dāng)我們創(chuàng)建一個弱引用的時候,系統(tǒng)會創(chuàng)建一個SizeTale县昂。
弱引用
弱引用不會對其引用的實例保持強引用肮柜,因而不會阻止ARC釋放被引用的實例,這個特性阻止了引用變?yōu)檠h(huán)引用七芭。聲明屬性或者變量時素挽,在前面加上weak關(guān)鍵字表明這是一個弱引用蔑赘。
由于弱引用不會強保持對實例的引用狸驳,所以說實例被釋放了弱引用仍舊引用著這個實例也是有可能预明。因此,ARC會在被引用的實例被釋放是自動地設(shè)置弱引用為nil耙箍。由于弱引用需要允許它們的值為nil撰糠,它們一定得是可選類型。
Unowned(無主引用)
和弱引用類似辩昆,無主引用不會牢牢保持住引用的實例阅酪。但是不像弱引用,總之汁针,無主引用假定是永遠有值的术辐。
根據(jù)蘋果的官方文檔的建議,當(dāng)我們知道兩個對象的生命周期并不相關(guān)施无,那么我們必須使用weak辉词。相反,非強引用對象擁有和強引用對象同樣或者更長的生命周期的話猾骡,則應(yīng)該使用unowned瑞躺。