
code_小馬swift
目錄
一、指針
1.為什么說指針是不安全的
2.指針類型
3.原始指針的使用
4.泛型指針的使用
5.內(nèi)存綁定
二、內(nèi)存管理
1.弱引用
2.Unowned
一、指針
1.為什么說指針是不安全的
-
在創(chuàng)建一個對象的時候,是需要在堆分配內(nèi)存空間。但是這個內(nèi)存空間的生命周期是有限的。如果我們使用指針指向這塊內(nèi)存空間,如果當(dāng)前內(nèi)存空間的生命周期結(jié)束了(
引用計數(shù)為0,系統(tǒng)回收內(nèi)存空間),那么我們當(dāng)前的指針就變成了未定義的行為了(野指針)。 -
:比如我們創(chuàng)建一個
count為10的數(shù)組,這個時候我們通過指針訪問到了index = 11的位置,這個時候就越界了,訪問了一個未知的內(nèi)存空間。 -
,也是不安全的。
2.指針類型
Swift中指針分為兩大類:
①typed pointer指定數(shù)據(jù)類型的指針;
②raw pointer未指定數(shù)據(jù)類型的指針(原生指針)。
基本上我們接觸到的指針類型有以下幾中
| Swift | Object-C | 說明 | 類型 |
|---|---|---|---|
| unsafePointer<T> | const T * | 指針及所指向的內(nèi)容都不可變 | typed pointer |
| unsafeMutablePointer<T> | T * | 指針及其所指向的內(nèi)存內(nèi)容均可變 | typed pointer |
| unsafeRawPointer | const void * | 指針指向的內(nèi)存區(qū)域未定 | 原生指針 |
| unsafeMutableRawPointer | void * | 同上 | 原生指針 |
| unsafeBufferPointer<T> | typed pointer | ||
| unsafeMutableBufferPointer<T> | typed pointer | ||
| unsafeRawBufferPointer | 原生指針 | ||
| unsafeMutableRawBufferPointer | 原生指針 |
3.原始指針的使用
三個基本概念:內(nèi)存大小size、步長信息stride、字節(jié)對齊alignment
struct YGTeacher {
var age: Int = 18
var haveCar: Bool = true
}
//內(nèi)存大小
print(MemoryLayout<YGTeacher>.size)
//步長:當(dāng)前指針需要移動的真實大小
print(MemoryLayout<YGTeacher>.stride)
//對齊
print(MemoryLayout<YGTeacher>.alignment)
- stride(步長):
如果在內(nèi)存當(dāng)中,我要存儲幾個連續(xù)的YGTeacher的實例,那這個步長信息指的是:
從第一個YGTeacher實例到下一個YGTeacher實例,它所跨越的長度信息。
YGTeacher.jpeg
分析上圖打印結(jié)果:
Int類型的age占了8個字節(jié)
Bool類型的haveCar占了1個字節(jié)
所以:YGTeacher這個結(jié)構(gòu)體實際大小size是9個字節(jié)
由于結(jié)構(gòu)體YGTeacher的對象內(nèi)存分配字節(jié)對齊alignment是8個字節(jié),
所以不足8字節(jié)的Bool類型就要補齊到8個字節(jié)(字節(jié)對齊原則),
所以當(dāng)前的步長信息stride是16個字節(jié)
- 使用
Raw Pointer來存儲4個整形的數(shù)據(jù):
這里我們需要選取的是UnsafeMutableRawPointer
如下圖所示:
存儲 :storeBytes
加載 :load
移動 :advanced

輸出臺信息.png

補充 storeBytes 存儲方法
4.泛型指針的使用
如下圖:不可變指針-只讀,指針和指針指向的地址都不可修改;
可變類型的指針,指針和指針指向的內(nèi)容都是可變的。
可變/不可變類型的指針
- 指定數(shù)據(jù)類型的可變指針
分配內(nèi)存空間allocate、初始化變量initialize、
取消初始設(shè)置deinitialize、deallocate釋放內(nèi)存空間
泛型指針的使用
- 我們可以通過以下方式來初始實話我們的指針
struct YGStruct {
var age: Int
var height: Double
}
//分配內(nèi)存空間,連續(xù)存儲5個結(jié)構(gòu)體的大小、明確指針內(nèi)存儲的數(shù)據(jù)類型為 YGStruct
var tPtr = UnsafeMutablePointer<YGStruct>.allocate(capacity: 5)
//存儲第一個內(nèi)存地址,賦值
tPtr[0] = YGStruct(age: 15, height: 160.0)
tPtr[1] = YGStruct(age: 21, height: 175.0)
tPtr[2] = YGStruct(age: 25, height: 181.0)
print("①",tPtr[0],"\n1=",tPtr[1],"\n2=",tPtr[2],"\n3=",tPtr[3],"\n4=",tPtr[4]);
//取消初始化釋放內(nèi)存空間
tPtr.deinitialize(count: 5)
tPtr.deallocate()
- 我們還可通過以下方式初始化指針
struct YGStruct_tow {
var age = 20
var height = 1.83
}
let p = UnsafeMutablePointer<YGStruct_tow>.allocate(capacity: 2)
p.initialize(to: YGStruct_tow())
p.advanced(by: MemoryLayout<YGStruct_tow>.stride).initialize(to: YGStruct_tow(age: 25, height: 1.83))
p.deinitialize(count: 2)
p.deallocate()
記住
initialize、advanced、deinitialize、deallocate要 成對兒 使用。
- 指針讀取Macho中的屬性名稱
首先分享一個優(yōu)化版machOView工具地址(爛蘋果)MachOView2.6.1
5.內(nèi)存綁定
二、內(nèi)存管理


