最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

swift內(nèi)存管理指針類型使用實(shí)例詳解

 更新時(shí)間:2022年11月24日 11:49:29   作者:i_erlich  
這篇文章主要為大家介紹了swift內(nèi)存管理指針類型使用實(shí)例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪

為什么說(shuō)指針不安全

  • 我們?cè)趧?chuàng)建一個(gè)對(duì)象的時(shí)候,是需要在堆上開辟內(nèi)存空間的 但是這個(gè)內(nèi)存空間的聲明周期是有限的 也就意味著如果使用指針指向這塊內(nèi)存空間,當(dāng)這塊內(nèi)存空間的生命周期結(jié)束(引用計(jì)數(shù)為0),那么當(dāng)前的指針就變成未定義的了
  • 創(chuàng)建的內(nèi)存空間是有邊界的,通過(guò)指針訪問(wèn)的內(nèi)存空間超過(guò)已開辟內(nèi)存空間的邊界,也就是訪問(wèn)了一個(gè)未知的內(nèi)存空間
  • 指針類型與內(nèi)存的值類型不一致,也不安全,這一點(diǎn)參考 swift指針&內(nèi)存管理-內(nèi)存綁定

指針類型

Swift中的指針分為兩類 typed pointer(指定指針數(shù)據(jù)類型) & raw pointer(原生指針-未指定指針數(shù)據(jù)類型)

如果需要開辟一段連續(xù)的內(nèi)存空間,就可以使用 unsafeBufferPointer, 當(dāng)然了unsafeMutableBufferPointer 就是可變的

連續(xù)的原生內(nèi)存空間 unsafeRawBufferPointer / unsafeMutableRawBufferPointer , 這種指針需要結(jié)合 指針內(nèi)存綁定來(lái)使用

原始指針-rawPointer 的使用

如何使用 rawPointer 來(lái)存儲(chǔ)4個(gè)整型的數(shù)據(jù)

在存儲(chǔ)之前,先了解幾個(gè)概念

print("MemoryLayout<Int>.size = \(MemoryLayout<Int>.size)")
print("MemoryLayout<Int>.stride = \(MemoryLayout<Int>.stride)")
print("MemoryLayout<Int>.alignment = \(MemoryLayout<Int>.alignment)")
print("MemoryLayout<Int32>.size = \(MemoryLayout<Int32>.size)")
print("MemoryLayout<Int32>.stride = \(MemoryLayout<Int32>.stride)")
print("MemoryLayout<Int32>.alignment = \(MemoryLayout<Int32>.alignment)")
print("MemoryLayout<Int16>.size = \(MemoryLayout<Int16>.size)")
print("MemoryLayout<Int16>.stride = \(MemoryLayout<Int16>.stride)")
print("MemoryLayout<Int16>.alignment = \(MemoryLayout<Int16>.alignment)")

結(jié)果:

MemoryLayout.size = 8

MemoryLayout.stride = 8

MemoryLayout.alignment = 8

MemoryLayout.size = 4

MemoryLayout.stride = 4

MemoryLayout.alignment = 4

MemoryLayout.size = 2

MemoryLayout.stride = 2

MemoryLayout.alignment = 2

MemoryLayout 是用來(lái)測(cè)定內(nèi)存的

stride是步長(zhǎng),也就是一段連續(xù)內(nèi)存空間 指定類型指針的偏移最小單位

alignment是對(duì)齊字節(jié),一段連續(xù)內(nèi)存空間,指令讀取內(nèi)存數(shù)據(jù),都是標(biāo)準(zhǔn)化操作,不會(huì)出現(xiàn)第一個(gè)整型讀了8字節(jié),下一個(gè)整型讀了4字節(jié)這樣

然后我們進(jìn)行 4個(gè)整型的數(shù)據(jù)的存儲(chǔ)

首先開辟一塊內(nèi)存空間

UnsafeMutableRawPointer.allocate(byteCount: Int, alignment: Int)

byteCount: 開辟內(nèi)存空間的總的字節(jié)大小

alignment: 連續(xù)內(nèi)存空間中 每一個(gè)整型數(shù)據(jù)的對(duì)齊大小

然后存儲(chǔ) - UnsafeMutableRawPointer - storeBytes(of: T, as: T.Type)

of - 存儲(chǔ)的數(shù)據(jù)

as - 存儲(chǔ)的數(shù)據(jù)的類型

let mP = UnsafeMutableRawPointer.allocate(
	byteCount: 4 * MemoryLayout<Int>.size, 
	alignment: MemoryLayout<Int>.stride)
	
for i in 0..<4 {
    mP.storeBytes(of: i, as: Int.self)
}
// 取出
for i in 0..<4 {
	let mV = mP.load(as: Int.self)
    let mV = mP.load(fromByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)
    print("mV ===> \(mV)")
}

結(jié)果

mV ===> 3

mV ===> 3

mV ===> 3

mV ===> 3

為什么不是 0, 1, 2, 3

這是因?yàn)?mP 指向 UnsafeMutableRawPointer.allocate 開辟出來(lái)的一段連續(xù)內(nèi)存空間首地址

mP.load(as: Int.self) 循環(huán)里每次取的都是 從首地址處取出 數(shù)據(jù),所以總是一樣的3

調(diào)整之后

let mP = UnsafeMutableRawPointer.allocate(
	byteCount: 4 * MemoryLayout<Int>.size, 
	alignment: MemoryLayout<Int>.stride)
	
for i in 0..<4 {
    mP.storeBytes(of: i, as: Int.self)
}
// 取出
for i in 0..<4 {
    let mV = mP.load(fromByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)
    print("mV ===> \(mV)")
}

結(jié)果

mV ===> 3

mV ===> 0

mV ===> 16

mV ===> 0

這又是為何

因?yàn)?mP.storeBytes(of: i, as: Int.self) 每次也只是往 mP指向的連續(xù)內(nèi)存空間的首地址里存儲(chǔ),所以最后存儲(chǔ)的 3會(huì)覆蓋前面的幾次寫值

let mP = UnsafeMutableRawPointer.allocate(
	byteCount: 4 * MemoryLayout<Int>.size, 
	alignment: MemoryLayout<Int>.stride)
	
for i in 0..<4 {
	// 正解
    mP.advanced(by: i * MemoryLayout<Int>.stride).storeBytes(of: i, as: Int.self)
}
// 取出
for i in 0..<4 {
    let mV = mP.load(fromByteOffset: i * MemoryLayout<Int>.stride, as: Int.self)
    print("mV ===> \(mV)")
}

結(jié)果

mV ===> 0

mV ===> 1

mV ===> 2

mV ===> 3

也可以直接 計(jì)算具體指針位置進(jìn)行寫值,前提是必須知道指針的類型才可以

for i in 0..<4 {
    (mP + i * MemoryLayout<Int>.stride).storeBytes(of: i, as: Int.self)
}

size/stride/alignment的理解

情況一

struct IFLObject1 {
    var age: Int
    var gender: Bool
}

print("MemoryLayout<IFLObject1>.size = \(MemoryLayout<IFLObject1>.size)")
print("MemoryLayout<IFLObject1>.stride = \(MemoryLayout<IFLObject1>.stride)")
print("MemoryLayout<IFLObject1>.alignment = \(MemoryLayout<IFLObject1>.alignment)")

結(jié)果

MemoryLayout.size = 9

MemoryLayout.stride = 16

MemoryLayout.alignment = 8

情況二

class IFLobject2 {
    var age: Int = 0
    var gender: Bool = true
    var heigh: Double = 170
    var heigh2: Double = 170
    var heigh3: Double = 170
    var heigh4: Double = 170
}
print("MemoryLayout<IFLobject2>.size = \(MemoryLayout<IFLObject2>.size)")
print("MemoryLayout<IFLobject2>.stride = \(MemoryLayout<IFLObject2>.stride)")
print("MemoryLayout<IFLobject2>.alignment = \(MemoryLayout<IFLObject2>.alignment)")

結(jié)果

MemoryLayout.size = 8

MemoryLayout.stride = 8

MemoryLayout.alignment = 8

與結(jié)構(gòu)體不同的是,struct屬于值類型,棧上開辟空間,class 堆上開辟內(nèi)存空間,指針大小為8字節(jié), 所以8字節(jié)對(duì)齊,步長(zhǎng)也是8字節(jié)

泛型指針的使用

泛型指針相比原生指針來(lái)說(shuō),就是當(dāng)前指針綁定到了具體的類型

泛型指針訪問(wèn)過(guò)程中,并不是使用store load 方法進(jìn)行存儲(chǔ) 取值操作,而是使用到泛型指針內(nèi)置的變量pointee

var age = 10
var age1 = withUnsafePointer(to: &age) {
    $0.pointee + 1
}
print("age1 = \(age1)")

結(jié)果

age1 = 11

另一種情況

var age = 10
withUnsafePointer(to: &age) {
    $0.pointee += 1
}

這種情況下 指針 0是不可變的,同時(shí)0 是不可變的,同時(shí)0是不可變的,同時(shí)0指向的內(nèi)容 $0.pointee也是不可變的, 如果要操作,調(diào)整如下

var age = 10
withUnsafeMutablePointer(to: &age) {
    $0.pointee += 1
}
print("age = \(age)")

結(jié)果

age = 11

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

var age = 10
let tPtr = UnsafeMutablePointer<Int>.allocate(capacity: 1)
tPtr.initialize(to: age)
print(tPtr.pointee)

結(jié)果

10

struct IFLObjStruct {
    var age: Int
    var height: Double
}
var tPtr = UnsafeMutablePointer<IFLObjStruct>.allocate(capacity: 5)
tPtr[0] = IFLObjStruct(age: 19, height: 170.0)
tPtr[1] = IFLObjStruct(age: 20, height: 171.0)
tPtr[2] = IFLObjStruct(age: 21, height: 172.0)
tPtr[3] = IFLObjStruct(age: 22, height: 173.0)
tPtr[4] = IFLObjStruct(age: 23, height: 174.0)

print(tPtr[4])

結(jié)果

IFLObjStruct(age: 23, height: 174.0)

還可以

struct IFLObjStruct {
    var age: Int
    var height: Double
}
var tPtr = UnsafeMutablePointer<IFLObjStruct>.allocate(capacity: 5)
tPtr[0] = IFLObjStruct(age: 19, height: 170.0)
tPtr[1] = IFLObjStruct(age: 20, height: 171.0)
tPtr[2] = IFLObjStruct(age: 21, height: 172.0)
tPtr[3] = IFLObjStruct(age: 22, height: 173.0)
tPtr[4] = IFLObjStruct(age: 23, height: 174.0)
tPtr.deinitialize(count: 5)
// 回收內(nèi)存空間
tPtr.deallocate()

tPtr = UnsafeMutablePointer<IFLObjStruct>.allocate(capacity: 5)
for i in 0..<5 {
    tPtr.advanced(by: i).initialize(to: IFLObjStruct(age: 19 + i * 5, height: 170.0 + Double(i * 5)))
}
for i in 0..<5 {
    print(tPtr.advanced(by: i).pointee)
}

結(jié)果

IFLObjStruct(age: 19, height: 170.0)

IFLObjStruct(age: 24, height: 175.0)

IFLObjStruct(age: 29, height: 180.0)

IFLObjStruct(age: 34, height: 185.0)

IFLObjStruct(age: 39, height: 190.0)

注意:

tPtr.advanced by 參數(shù) 含義是 只需要標(biāo)明移動(dòng)多少個(gè)指針內(nèi)存單位, 并不需要計(jì)算具體移動(dòng)的內(nèi)存塊字節(jié)大小,

因?yàn)?泛型指針已經(jīng) 指明了當(dāng)前內(nèi)存 綁定的具體類型, 與原生指針 adviced by 參數(shù)有所區(qū)別

一般情況下,我們會(huì)在 defer 中,也就是當(dāng)前程序運(yùn)行完成之后, 執(zhí)行 deinitialize 與 deallocate

以上就是swift內(nèi)存管理指針類型使用實(shí)例詳解的詳細(xì)內(nèi)容,更多關(guān)于swift內(nèi)存管理指針類型的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • Swift中類與結(jié)構(gòu)的初始化示例解析

    Swift中類與結(jié)構(gòu)的初始化示例解析

    這篇文章主要為大家介紹了Swift中類與結(jié)構(gòu)的初始化解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步早日升職加薪
    2022-03-03
  • Swift算法之二叉樹實(shí)現(xiàn)的方法示例

    Swift算法之二叉樹實(shí)現(xiàn)的方法示例

    二叉樹是計(jì)算機(jī)科學(xué)中最基本也是最重要的樹型結(jié)構(gòu),最常見的二叉樹生成算法通常是使用遞歸或者其他描述類語(yǔ)言的方法來(lái)實(shí)現(xiàn)。本文主要介紹了Swift算法之二叉樹實(shí)現(xiàn)的方法,文中介紹的非常詳細(xì),對(duì)大家具有一定的參考價(jià)值,需要的朋友們下面來(lái)一起看看吧。
    2017-03-03
  • Swift編程中用以管理內(nèi)存的自動(dòng)引用計(jì)數(shù)詳解

    Swift編程中用以管理內(nèi)存的自動(dòng)引用計(jì)數(shù)詳解

    這篇文章主要介紹了Swift編程中用以管理內(nèi)存的自動(dòng)引用計(jì)數(shù)詳解,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Swift實(shí)現(xiàn)復(fù)數(shù)計(jì)算器

    Swift實(shí)現(xiàn)復(fù)數(shù)計(jì)算器

    這篇文章主要為大家詳細(xì)介紹了Swift實(shí)現(xiàn)復(fù)數(shù)計(jì)算器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01
  • Swift如何為設(shè)置中心添加常用功能

    Swift如何為設(shè)置中心添加常用功能

    這篇文章主要給大家介紹了關(guān)于Swift如何為設(shè)置中心添加常用功能的相關(guān)資料,包含了跳轉(zhuǎn)到AppStore、郵件反饋功能、系統(tǒng)分享功能以及打開某些網(wǎng)址等功能,需要的朋友可以參考借鑒,下面來(lái)一起看看吧
    2018-05-05
  • 詳解Swift中的數(shù)據(jù)類型類型轉(zhuǎn)換

    詳解Swift中的數(shù)據(jù)類型類型轉(zhuǎn)換

    Swift中的類型轉(zhuǎn)換可以結(jié)合類的繼承等面向?qū)ο蟮木幊烫匦詠?lái)進(jìn)行,本文中我們就來(lái)詳解Swift中的數(shù)據(jù)類型類型轉(zhuǎn)換,需要的朋友可以參考下
    2016-07-07
  • SwiftUI中@ViewBuilder的相關(guān)知識(shí)點(diǎn)解密

    SwiftUI中@ViewBuilder的相關(guān)知識(shí)點(diǎn)解密

    IOS開發(fā)目前最主流的框架當(dāng)屬SwiftUI了,這篇文章主要給大家介紹了關(guān)于SwiftUI中@ViewBuilder的一些相關(guān)知識(shí)點(diǎn),文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2021-07-07
  • 深入理解Swift語(yǔ)言中的閉包機(jī)制

    深入理解Swift語(yǔ)言中的閉包機(jī)制

    這篇文章主要介紹了Swift語(yǔ)言中的閉包機(jī)制,是Swift入門學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Swift版使用ThPullRefresh實(shí)現(xiàn)下拉上拉刷新數(shù)據(jù)

    Swift版使用ThPullRefresh實(shí)現(xiàn)下拉上拉刷新數(shù)據(jù)

    這篇文章主要介紹了Swift版使用ThPullRefresh實(shí)現(xiàn)下拉上拉刷新數(shù)據(jù),需要的朋友可以參考下
    2016-01-01
  • Swift實(shí)現(xiàn)表格視圖單元格單選(1)

    Swift實(shí)現(xiàn)表格視圖單元格單選(1)

    這篇文章主要為大家詳細(xì)介紹了Swift實(shí)現(xiàn)表格視圖單元格單選,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2022-01-01

最新評(píng)論

南阳市| 普安县| 泸州市| 乌海市| 铜山县| 行唐县| 永川市| 华蓥市| 织金县| 黑水县| 山丹县| 玉溪市| 高唐县| 东乌珠穆沁旗| 通榆县| 武安市| 镇安县| 贞丰县| 监利县| 曲靖市| 本溪市| 宜州市| 玉田县| 东兴市| 酒泉市| 虹口区| 运城市| 临颍县| 论坛| 益阳市| 嘉禾县| 凌云县| 区。| 洪湖市| 根河市| 福建省| 福贡县| 攀枝花市| 大渡口区| 错那县| 万州区|