code_小馬swift
目錄
一搞莺、指針
1.為什么說指針是不安全的
2.指針類型
3.原始指針的使用
4.泛型指針的使用
5.內存綁定
二缤苫、內存管理
1.弱引用
2.Unowned
一较沪、指針
1.為什么說指針是不安全的
-
在創(chuàng)建一個對象的時候优俘,是需要在堆分配內存空間玫膀。但是這個內存空間的生命周期是有限的封断。如果我們使用指針指向這塊內存空間斯辰,如果當前內存空間的生命周期結束了(
引用計數為0,系統(tǒng)回收內存空間
)坡疼,那么我們當前的指針就變成了未定義的行為了(野指針
)椒涯。 -
:比如我們創(chuàng)建一個
count為10
的數組,這個時候我們通過指針訪問到了index = 11
的位置回梧,這個時候就越界了废岂,訪問了一個未知的內存空間。 -
狱意,也是不安全的湖苞。
2.指針類型
Swift中指針分為兩大類:
①typed pointer
指定數據類型的指針;
②raw pointer
未指定數據類型的指針(原生指針)详囤。
基本上我們接觸到的指針類型有以下幾中
Swift | Object-C | 說明 | 類型 |
---|---|---|---|
unsafePointer<T> | const T * | 指針及所指向的內容都不可變 | typed pointer |
unsafeMutablePointer<T> | T * | 指針及其所指向的內存內容均可變 | typed pointer |
unsafeRawPointer | const void * | 指針指向的內存區(qū)域未定 | 原生指針 |
unsafeMutableRawPointer | void * | 同上 | 原生指針 |
unsafeBufferPointer<T> | typed pointer | ||
unsafeMutableBufferPointer<T> | typed pointer | ||
unsafeRawBufferPointer | 原生指針 | ||
unsafeMutableRawBufferPointer | 原生指針 |
3.原始指針的使用
三個基本概念:內存大小size财骨、步長信息stride镐作、字節(jié)對齊alignment
struct YGTeacher {
var age: Int = 18
var haveCar: Bool = true
}
//內存大小
print(MemoryLayout<YGTeacher>.size)
//步長:當前指針需要移動的真實大小
print(MemoryLayout<YGTeacher>.stride)
//對齊
print(MemoryLayout<YGTeacher>.alignment)
- stride(步長):
如果在內存當中,我要存儲幾個連續(xù)的YGTeacher的實例隆箩,那這個步長信息指的是:
從第一個YGTeacher實例到下一個YGTeacher實例该贾,它所跨越的長度信息。
YGTeacher.jpeg
分析上圖打印結果:
Int
類型的age占了8個字節(jié)
Bool
類型的haveCar占了1個字節(jié)
所以:YGTeacher
這個結構體實際大小size
是9個字節(jié)
由于結構體YGTeacher的對象內存分配字節(jié)對齊alignment
是8個字節(jié)
捌臊,
所以不足8字節(jié)的Bool類型就要補齊
到8個字節(jié)(字節(jié)對齊原則)杨蛋,
所以當前的步長信息stride
是16個字節(jié)
- 使用
Raw Pointer
來存儲4個整形的數據:
這里我們需要選取的是UnsafeMutableRawPointer
如下圖所示:
存儲 :storeBytes
加載 :load
移動 :advanced
輸出臺信息.png
補充 storeBytes 存儲方法
4.泛型指針的使用
如下圖:不可變指針-只讀,指針和指針指向的地址都不可修改理澎;
可變類型的指針逞力,指針和指針指向的內容都是可變的。
可變/不可變類型的指針
- 指定數據類型的可變指針
分配內存空間allocate糠爬、初始化變量initialize寇荧、
取消初始設置deinitialize、deallocate釋放內存空間
泛型指針的使用
- 我們可以通過以下方式來初始實話我們的指針
struct YGStruct {
var age: Int
var height: Double
}
//分配內存空間执隧,連續(xù)存儲5個結構體的大小揩抡、明確指針內存儲的數據類型為 YGStruct
var tPtr = UnsafeMutablePointer<YGStruct>.allocate(capacity: 5)
//存儲第一個內存地址,賦值
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]);
//取消初始化釋放內存空間
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.內存綁定
二寻仗、內存管理