第二十九篇:Swift指針和內(nèi)存管理

指針

為什么說指針不安全
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ù)類型的指針(原生指針)?;旧衔覀兘佑|到的指針類型有以下幾種:


8261670412046_.pic.jpg

泛型指針的使用

  這里的泛型指針相比較原生指針來說,其實就是指定當前指針已經(jīng)綁定到了具體的類型。在進行泛型指針訪問的過程中,我們并不是使用load和store方法來進行存儲操作,這里我們使用到當前泛型指針內(nèi)置的變量pointee。
8281670425941_.pic.jpg

還有一種方式就是直接分配內(nèi)存

8291670426030_.pic.jpg

Swift與OC里的不同的是,直接定義指針存儲的類型(這里用存的是LGStruct類型),其中通過allocate去創(chuàng)建,然后通過deallocate()去釋放。

8301670426215_.pic.jpg

內(nèi)存綁定

Swift提供了三種不同的API來綁定/重新綁定指針:
1)assumingMemoryBound(to:)
2)bindMemory(to:capacity:)
3)withMemoryRebound(to:capacity:body:)(臨時改變內(nèi)存綁定)

下面是用assumingMemoryBound來的:這個是告知編譯器我當前是Int類型,不需要額外進行檢查,直接使用。


8391670478559_.pic.jpg

內(nèi)存管理

swift中使用自動引用計數(shù)(ARC)機制來追蹤和管理內(nèi)存。

首先我們先找到 RefCount 的定義,這里我們在HeapObject.h文件中

8401670505912_.pic.jpg

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


8411670507641_.pic.jpg
8421670509157_.pic.jpg

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

8431670578808_.pic.jpg
8441670578840_.pic.jpg

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


image.png

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


8461670582053_.pic.jpg

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


8471670582172_.pic.jpg

Swift中存在兩種引用計數(shù),一種是inlineRefCount是,一種是SideTableRefCounts。Side Table是一種類名為

HeapObjectSizeTableEntry的結構,里面也有RefCounts成員,是內(nèi)部是SizeTableRefCountBits,其實就是原來的uint64_t加上一個存儲弱引用數(shù)的uint32_t。

8481670582504_.pic.jpg

這里我們來總結一下我們當前的引用計數(shù),一個對象在初始化的時候后是沒有SizeTable的,當我們創(chuàng)建一個弱引用的時候,系統(tǒng)會創(chuàng)建一個SizeTale。

弱引用

弱引用不會對其引用的實例保持強引用,因而不會阻止ARC釋放被引用的實例,這個特性阻止了引用變?yōu)檠h(huán)引用。聲明屬性或者變量時,在前面加上weak關鍵字表明這是一個弱引用。

由于弱引用不會強保持對實例的引用,所以說實例被釋放了弱引用仍舊引用著這個實例也是有可能。因此,ARC會在被引用的實例被釋放是自動地設置弱引用為nil。由于弱引用需要允許它們的值為nil,它們一定得是可選類型。

Unowned(無主引用)

和弱引用類似,無主引用不會牢牢保持住引用的實例。但是不像弱引用,總之,無主引用假定是永遠有值的。

根據(jù)蘋果的官方文檔的建議,當我們知道兩個對象的生命周期并不相關,那么我們必須使用weak。相反,非強引用對象擁有和強引用對象同樣或者更長的生命周期的話,則應該使用unowned。

8491670589662_.pic.jpg

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

8501670592083_.pic.jpg
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內(nèi)容

  • 指針 為什么說指針不安全 比如我們在創(chuàng)建一個對象的時候,是需要在堆分配內(nèi)存空間的。但是這個內(nèi)存空間的聲明周期是有限...
    晨曦的簡書閱讀 590評論 0 1
  • 一、指針 ?? 1、指針類型 ??Swift中的指針分為兩類:指定數(shù)據(jù)類型的指針(typed pointer);未...
    spyn_n閱讀 1,086評論 1 4
  • 一、指針 1.1 為什么說指針不安全 ?如我們在創(chuàng)建?個對象的時候,是需要在堆分配內(nèi)存空間的。但是這個內(nèi)存空間的生...
    常在士心閱讀 596評論 0 1
  • 一.為什么說指針不安全 比如我們在創(chuàng)建一個對象的時候,是需要在堆分配內(nèi)存空間的。但是這個內(nèi)存空間的聲明周期是有限的...
    MissStitch丶閱讀 1,051評論 1 8
  • 一:指針 1. 指針的定義 Swift 中引用了某個引用類型實例的常量或變量,與 C 語言中的指針類似,不過它并不...
    Lee_Toto閱讀 676評論 0 3

友情鏈接更多精彩內(nèi)容