指針
為什么說指針不安全
1)比如我們在創(chuàng)建一個對象的時候,是需要在堆分配內(nèi)存空間的。但是這個內(nèi)存空間的聲明周期是有限的,也就意味著如果我們使用指針指向這塊內(nèi)容空間,如果當前內(nèi)存空間的生命周期到了(引用計數(shù)為0),那么我們當前的指針是不是就變成了未定義的行為了。
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ù)類型的指針(原生指針)?;旧衔覀兘佑|到的指針類型有以下幾種:

泛型指針的使用
這里的泛型指針相比較原生指針來說,其實就是指定當前指針已經(jīng)綁定到了具體的類型。在進行泛型指針訪問的過程中,我們并不是使用load和store方法來進行存儲操作,這里我們使用到當前泛型指針內(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來的:這個是告知編譯器我當前是Int類型,不需要額外進行檢查,直接使用。

內(nèi)存管理
swift中使用自動引用計數(shù)(ARC)機制來追蹤和管理內(nèi)存。
首先我們先找到 RefCount 的定義,這里我們在HeapObject.h文件中

在源碼里通過分析,可以得到引用計數(shù)是存放中RefcountBitsInt里,這個是一個64bit的位 域計數(shù),下面是各個地址存儲的信息。


下面是對應的swift里的引用計數(shù)的代碼,使用了swift_retain函數(shù),進行refCounts的增加。


下面這段代碼就產(chǎn)生了兩個實例對象強引用,swift提供了兩種辦法用來解決使用類的屬性時所遇到的循環(huán)強引用問題,弱引用(weak reference )和無主引用(unowned reference)。

聲明一個weak變量相當于定義了一個weakrefrence對象

同時在swift里的引用計數(shù)用到了sideTable來存儲:

Swift中存在兩種引用計數(shù),一種是inlineRefCount是,一種是SideTableRefCounts。Side Table是一種類名為
HeapObjectSizeTableEntry的結構,里面也有RefCounts成員,是內(nèi)部是SizeTableRefCountBits,其實就是原來的uint64_t加上一個存儲弱引用數(shù)的uint32_t。

這里我們來總結一下我們當前的引用計數(shù),一個對象在初始化的時候后是沒有SizeTable的,當我們創(chuàng)建一個弱引用的時候,系統(tǒng)會創(chuàng)建一個SizeTale。
弱引用
弱引用不會對其引用的實例保持強引用,因而不會阻止ARC釋放被引用的實例,這個特性阻止了引用變?yōu)檠h(huán)引用。聲明屬性或者變量時,在前面加上weak關鍵字表明這是一個弱引用。
由于弱引用不會強保持對實例的引用,所以說實例被釋放了弱引用仍舊引用著這個實例也是有可能。因此,ARC會在被引用的實例被釋放是自動地設置弱引用為nil。由于弱引用需要允許它們的值為nil,它們一定得是可選類型。
Unowned(無主引用)
和弱引用類似,無主引用不會牢牢保持住引用的實例。但是不像弱引用,總之,無主引用假定是永遠有值的。
根據(jù)蘋果的官方文檔的建議,當我們知道兩個對象的生命周期并不相關,那么我們必須使用weak。相反,非強引用對象擁有和強引用對象同樣或者更長的生命周期的話,則應該使用unowned。

當遇到循環(huán)引用我們用weak修飾時候,對象會被提前釋放,如果使用withExtendedLifetime去延遲將要被釋放的對象的生命周期。
