Swift 指針&內(nèi)存管理&Enum&optional

指針不是安全的

1.野指針。指針指向?qū)ο筢尫牛羔樧優(yōu)橐爸羔?/p>

2.指針超出內(nèi)存空間邊界訪問。如數(shù)組越界

3.原?指針和類型指針的轉(zhuǎn)換,會(huì)有數(shù)據(jù)丟失

指針類型

Swift中的指針分為兩類,

類型指針: typed pointer 指定數(shù)據(jù)類型指針,

原?指針: raw pointer 未指定數(shù)據(jù)類型的指針


指針類型

原生指針

1.創(chuàng)建UnsafeMutableRawPointer.allocate

2.銷毀指針deallocate()

3.儲(chǔ)存值storeBytes(of: i, as:?Int.self)

4.讀取值load(fromByteOffset: i?*?MemoryLayout<Int>.stride, as:?Int.self)

3.移動(dòng)指針advanced(by: i?*?MemoryLayout<Int>.stride)

func demo1() {

? ? ? let p = UnsafeMutableRawPointer.allocate(byteCount: 4 * 8, alignment: 8)

? ? ? defer {

?? ? ? ? print("32")

?? ? ? ? p.deallocate()

? ? ? }

?? ? ?

? ? ? for i in 0..<4 {

?? ? ? ? p.advanced(by: i * MemoryLayout<Int>.stride).storeBytes(of: i, as: Int.self)

? ? ? }

? ? ? print(p)

? ? ? for i in 0..<4 {

?? ? ? ? let value = p.load(fromByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)

?? ? ? ? print(value)

? ? ? }

?? }

類型指針

第?種?式就是直接分配內(nèi)存?

1.創(chuàng)建UnsafeMutablePointer<LGPerson>.allocate

2.銷毀??p.deinitialize(count:?5) ->??p.deallocate()

3.儲(chǔ)存值p[0] ?= ...

4.讀取值?pointee屬性

let p = UnsafeMutablePointer<LGPerson>.allocate(capacity: 5)

? ? ? defer {

?? ? ? ? p.deinitialize(count: 5)

?? ? ? ? p.deallocate()

? ? ? }

? ? ? p[0] = LGPerson(age: 18, sex: true, married: true)

? ? ? p[1] = LGPerson(age: 19, sex: true, married: true)

? ? ? print(p)

? ? ? print(p.pointee)

第二種方式

通過已有變量獲取?

通過withUnsafePointer(to: &age) { $0.pointee?+?21} 獲取當(dāng)前變量的地址

? ??var age = 18

? ? ? age =withUnsafePointer(to: &age) { ptr in

?? ? ? ? return ptr.pointee + 21

? ? ? }

? ? ? print(age)

指針綁定API

1.assumingMemoryBound(to:) ?避免編譯器類型檢查

2.原生指針 ?bindMemory(to: capacity:)?更改內(nèi)存綁定的類型。如果當(dāng)前內(nèi)存還沒有類型綁定,則將?次綁定為該類型;否則重新綁定該類 型,并且內(nèi)存中所有的值都會(huì)變成該類型

3.類型指針 withMemoryRebound(to: capacity: body:)指針使用過程中臨時(shí)更改內(nèi)存綁定類型

指針使用實(shí)例

1.解析類的數(shù)據(jù)結(jié)構(gòu)

類的結(jié)構(gòu)體指針內(nèi)存布局

struct HeapObject {

?? var metadata: UnsafeRawPointer

?? var refCounted1: UInt32

?? var refCounted2: UInt32

}

struct Metadata{

? ? var kind: Int

? ? var superClass: Any.Type

? ? var cacheData: (Int, Int)

? ? var data: Int

? ? var classFlags: Int32

? ? var instanceAddressPoint: UInt32

? ? var instanceSize: UInt32

? ? var instanceAlignmentMask: UInt16

? ? var reserved: UInt16

? ? var classSize: UInt32

? ? var classAddressPoint: UInt32

? ? var typeDescriptor: UnsafeMutableRawPointer

? ? var iVarDestroyer: UnsafeRawPointer

}

1. 獲取實(shí)例的內(nèi)存地址(原生指針)?Unmanaged.passUnretained(t?as?AnyObject).toOpaque()

2.綁定具體類型(HeapObject)

let t = LGTeacher()

? ? ? let objRawPtr = Unmanaged.passUnretained(t as AnyObject).toOpaque()

? ? ? let objPtr = objRawPtr.bindMemory(to: HeapObject.self, capacity: MemoryLayout.stride(ofValue: t))

? ? ? let tMetaData = objPtr.pointee.metadata.bindMemory(to: Metadata.self, capacity: MemoryLayout<Metadata>.stride)

? ? ? print(MemoryLayout.stride(ofValue: t))

? ? ? print(objPtr.pointee)

? ? ? print(tMetaData.pointee)

? ? ? print("end")

2.UInt64 與指針轉(zhuǎn)換

1.UInt64 ->?指針?UnsafePointer<UInt32>.init(bitPattern:?Int(exactly: dataLoAddress) ???0)?

2.指針 ->?UInt64?UInt64(bitPattern:?Int64(Int(bitPattern: mhHeaderPtr)))

let mhHeaderPtr_IntRepresentation = UInt64(bitPattern: Int64(Int(bitPattern: mhHeaderPtr)))

? ? var dataLoAddress = mhHeaderPtr_IntRepresentation + offset

? ? var dataLoContent = UnsafePointer<UInt32>.init(bitPattern: Int(exactly: dataLoAddress) ?? 0)?.pointee

內(nèi)存管理

Swift?中使??動(dòng)引?計(jì)數(shù)(ARC)機(jī)制來追蹤和管理內(nèi)存。

使用8字節(jié)存儲(chǔ)當(dāng)前的引?計(jì)數(shù)的。

weak 關(guān)鍵字,原來的 uint64_t 加上?個(gè)存儲(chǔ)弱引?數(shù)的 uint32_t

1.正常情況InlineRefCountBits ??strong RC?+?unowned RC?+?flags ?64位

2.加weak ?HeapObjectSideTableEntry ?strong RC?+?unowned RC?+?weak RC?+?flags ?64+32

HeapObject {?

????isa?

????InlineRefCounts {?

????????atomic<InlineRefCountBits>?{?

????????????strong RC?+?unowned RC?+?flags?

????????OR

????????HeapObjectSideTableEntry*?

????}?

????}?

}

HeapObjectSideTableEntry {?

????SideTableRefCounts {?

????????object pointer?

????????atomic<SideTableRefCountBits>?{?

????????strong RC?+?unowned RC?+?weak RC?+?flags?

????}?

????}?

}?

let t = LGTeacher()

let t1 = t

let t2 = t

print("end")

My Mac 調(diào)試的


引用計(jì)數(shù)

1. MetaData 內(nèi)存地址

2.引用計(jì)數(shù)


二進(jìn)制示意圖

let?t?=?LGTeacher(),?strong RC?+?unowned RC?+?flags ,?strong RC 在33位是1,?unowned RC在1位是1,flags在0位是1

Weak VS unowned?

如果兩個(gè)對(duì)象的?命周期完全和對(duì)?沒關(guān)系(其中??什么時(shí)候賦值為nil,對(duì)對(duì)?都沒影響),請(qǐng)? weak?

如果你的代碼能確保:其中?個(gè)對(duì)象銷毀,另?個(gè)對(duì)象也要跟著銷毀,這時(shí)候,可以(謹(jǐn)慎)? unowned?

常見閉包循環(huán)引用

1. 類有個(gè)complateCallback 閉包

2.complateCallback 閉包 使用實(shí)例 t.age

解決方法:?[unowned?t]?

let t = LGTeacher()

? ? ? t.complateCallback = { [unowned t] in

?? ? ? ? t.age += 1

? ? ? }

閉包循環(huán)引用

不加unowned 或 weak ,不執(zhí)行deinit{} 方法的

加入unowned 或 weak ,執(zhí)行deinit{} 方法的

捕獲列表

? ????var age = 0

? ? ? var height = 0.0

? ? ? let closure = {[age] in

?? ? ? ? print(age)

?? ? ? ? print(height)

? ? ? }

? ? ? age =10

? ? ? height =1.88

? ? ? closure()

輸出:age =??0 ?height =?1.88

[age] 捕獲閉包之前的age值

height沒有出現(xiàn)在捕獲列表中,height值是閉包調(diào)用前height的值

Enum

內(nèi)存大小

MemoryLayout<Int>.size內(nèi)存實(shí)際大小

MemoryLayout<LGPerson>.stride內(nèi)存步長

MemoryLayout<LGPerson>.alignment 字節(jié)對(duì)齊

enum Weak: Int {

?? case MONDAY = 0

?? case TUEDAY

?? case WEDDAY

?? case THUDAY

?? case FRIDAY

?? case SATDAY

?? case SUNDAY

}

1. enum 的原始值rawValue,需要明確原始值類型

Weak.MONDAY.rawValue

Weak枚舉內(nèi)存大小 1字節(jié)

var a = Weak.MONDAY

MemoryLayout.size(ofValue: a) ?1

MemoryLayout.stride(ofValue: a) ?1

enum LGEnum {

//? case test_one(Bool)

? ? case test_two(Int)

?? case test_three

?? case test_four

}

MemoryLayout<LGEnum>.size ?9

MemoryLayout<LGEnum>.stride 16

enum 內(nèi)存大小

關(guān)聯(lián)值 所有參數(shù)內(nèi)存大小 + 1字節(jié)

?sizeof(Int) * 3 + sizeof(rawVlaue)

關(guān)鍵值indirect

enum List<Element>{

? ? case end

?? indirect case node(Element, next: List<Element>)

}

enum 前面加indirect,創(chuàng)建List枚舉類型,調(diào)用swift_allocObject方法

?indirect?case?node,是node時(shí)才調(diào)用swift_allocObject方法,end不調(diào)用的

Optional是一個(gè)枚舉

enum MyOptional<Value> {

?? case some(Value)

?? case none

}

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 229,362評(píng)論 6 537
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 99,013評(píng)論 3 423
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 177,346評(píng)論 0 382
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經(jīng)常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 63,421評(píng)論 1 316
  • 正文 為了忘掉前任,我火速辦了婚禮,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 72,146評(píng)論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 55,534評(píng)論 1 325
  • 那天,我揣著相機(jī)與錄音,去河邊找鬼。 笑死,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,585評(píng)論 3 444
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 42,767評(píng)論 0 289
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 49,318評(píng)論 1 335
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 41,074評(píng)論 3 356
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 43,258評(píng)論 1 371
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,828評(píng)論 5 362
  • 正文 年R本政府宣布,位于F島的核電站,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 44,486評(píng)論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,916評(píng)論 0 28
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 36,156評(píng)論 1 290
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 51,993評(píng)論 3 395
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 48,234評(píng)論 2 375

推薦閱讀更多精彩內(nèi)容