欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

深入探究Swift枚舉關(guān)聯(lián)值的內(nèi)存

 更新時(shí)間:2020年08月18日 14:45:07   作者:Sunxb  
這篇文章主要給大家介紹了關(guān)于Swift枚舉關(guān)聯(lián)值的內(nèi)存的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者使用Swift具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
enum Season {
 case Spring, Summer, Autumn, Winter
}
let s = Season.Spring

這是枚舉最基礎(chǔ)的用法,但是在swift中,對(duì)枚舉的功能進(jìn)行了加強(qiáng),也就是關(guān)聯(lián)值。

關(guān)聯(lián)值可以將額外信息附加到 enum case中,像下面這樣子。

enum Test {
 case test1(v1: Int, v2: Int, v3: Int)
 case test2(v1: Int, v2: Int)
 case test3(v1: Int)
 case test4
}
let t = Test.test1(v1: 1, v2: 2, v3: 3)
 
switch t {
case .test1(let v1, let v2, let v3):
 print(v1, v2, v3)
default:
 break
}
// 輸出: 1 2 3

我們可以看到,在我們創(chuàng)建一個(gè)枚舉值t的時(shí)候,設(shè)置他的選項(xiàng)為test1,同時(shí)可以關(guān)聯(lián)3個(gè)Int類型的值,然后在switch中,我們還可以把這3個(gè)Int值取出來(lái)進(jìn)行使用。

我們今天的主要任務(wù)就是探索一下有關(guān)聯(lián)值的枚舉類型,再底層的內(nèi)存布局是什么樣子的,這些值都是怎么儲(chǔ)存的。

在OC中我們使用sizeOf此類方法,可以輸出一個(gè)變量占用內(nèi)存的大小,在swift中也有此類的工作類,那就是MemoryLayout。

print(MemoryLayout<Int>.size)// 實(shí)際使用內(nèi)存大小
print(MemoryLayout<Int>.stride)//分配內(nèi)存大小
print(MemoryLayout<Int>.alignment)//內(nèi)存對(duì)其參數(shù)

// 輸出 8 8 8 

上面的例子是只是簡(jiǎn)單的實(shí)例MemoryLayout的用法,這個(gè)我們知道,在64位的系統(tǒng)中Int類型確實(shí)是占用8個(gè)字節(jié)(64位)。接下來(lái)我們就看一下枚舉的內(nèi)存占用情況。

點(diǎn)擊Xcode菜單欄中的Debug -> Debug Workflow -> View Memory,然后在下面紅色框中輸入變量的內(nèi)存地址,就可以看到變量的內(nèi)存使用情況。

使用swift后,從xcode沒(méi)法直接打印變量的內(nèi)存地址,這里我們使用了github上的一個(gè)工具類來(lái)幫助我們輸出變量的內(nèi)存地址。

準(zhǔn)備工作完成后,我們先從最基礎(chǔ)的枚舉開(kāi)始。

enum Season {
 case Spring, Summer, Autumn, Winter
}
print("實(shí)際占用:",MemoryLayout<Season>.size)
print("分配:",MemoryLayout<Season>.stride)
print("對(duì)齊參數(shù):", MemoryLayout<Season>.alignment)
 
var s = Season.Spring
print("內(nèi)存地址",Mems.ptr(ofVal: &s))
 
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &s, alignment: .one))
 
s = Season.Summer
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &s, alignment: .one))
 
s = Season.Autumn
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &s, alignment: .one))
 
s = Season.Winter
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &s, alignment: .one))

注:Mems.memStr可以直接打印內(nèi)存數(shù)據(jù),這樣我們就不用每次拿到地址再去工具中看了

實(shí)際占用: 1
分配: 1
對(duì)齊參數(shù): 1
內(nèi)存地址 0x00007ffee753f0f0
內(nèi)存數(shù)據(jù) 0x00
內(nèi)存數(shù)據(jù) 0x01
內(nèi)存數(shù)據(jù) 0x02
內(nèi)存數(shù)據(jù) 0x03

我們可以看到這種普通的枚舉類型,只占用一個(gè)字節(jié)。而且通過(guò)我們對(duì)變量設(shè)置不同的枚舉值,打印的這一個(gè)字節(jié)的數(shù)據(jù)也是不同的,其實(shí)也就是使用這一個(gè)字節(jié)通過(guò)設(shè)置不同的數(shù)值來(lái)表示不同的枚舉值,這樣的話其實(shí)可以至少儲(chǔ)存0x00-0xFF共256個(gè)值。那如果超過(guò)256個(gè)case呢?其實(shí)我覺(jué)得沒(méi)有必要考慮這種情況,枚舉本來(lái)設(shè)計(jì)出就是為了區(qū)分有限中情況,如果太多,就像200多個(gè),那完全可以使用Int來(lái)設(shè)置不同的值了,就沒(méi)必要用枚舉了,當(dāng)然,如果您愿意探究一下的話也是可以的。

接下來(lái)我們使用一個(gè)帶關(guān)聯(lián)值的枚舉來(lái)看一下。

enum Test {
 case test1(v1: Int, v2: Int, v3: Int)
 case test2(v1: Int, v2: Int)
 case test3(v1: Int)
 case test4
}
 
print("實(shí)際占用:",MemoryLayout<Test>.size)
print("分配:",MemoryLayout<Test>.stride)
print("對(duì)齊參數(shù):", MemoryLayout<Test>.alignment)
 
var t = Test.test1(v1: 1, v2: 2, v3: 3)
print("內(nèi)存地址",Mems.ptr(ofVal: &t))
 
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &t, alignment: .one))
 
t = Test.test2(v1: 4, v2: 5)
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &t, alignment: .one))
 
t = Test.test3(v1: 6)
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &t, alignment: .one))
 
t = Test.test4
print("內(nèi)存數(shù)據(jù)",Mems.memStr(ofVal: &t, alignment: .one))

下面是輸出, 為了能直觀一下,我給插了幾個(gè)換行

實(shí)際占用: 25
分配: 32
對(duì)齊參數(shù): 8
內(nèi)存地址 0x00007ffee0afe0d8
內(nèi)存數(shù)據(jù)
0x01 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x02 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00
內(nèi)存數(shù)據(jù)
0x04 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x05 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x01
0x00 0x00 0x00 0x00 0x00 0x00 0x00
內(nèi)存數(shù)據(jù)
0x06 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x02
0x00 0x00 0x00 0x00 0x00 0x00 0x00
內(nèi)存數(shù)據(jù)
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x00
0x03
0x00 0x00 0x00 0x00 0x00 0x00 0x00

實(shí)際占用了25個(gè)字節(jié),我們至少可以確定,枚舉的關(guān)聯(lián)值是存儲(chǔ)在枚舉值的內(nèi)存中的。

但是通過(guò)這一個(gè)例子其實(shí)可能還看不出有什么規(guī)律,大家可以多用幾個(gè)例子來(lái)驗(yàn)證,這是我就直接說(shuō)結(jié)論了。

有關(guān)聯(lián)值得枚舉實(shí)際占用的內(nèi)存是最多關(guān)聯(lián)值占用的內(nèi)存+1,在我們這個(gè)Test中,test1的關(guān)聯(lián)值是最多的,有3個(gè)Int類型的關(guān)聯(lián)值,所以要8*3=24字節(jié)來(lái)存放關(guān)聯(lián)值,但是還需要一個(gè)字節(jié)來(lái)儲(chǔ)存(辨別)是哪一個(gè)case。

帶著這個(gè)結(jié)論我們看一下輸出的結(jié)果:

當(dāng)t=.test1時(shí),前面24個(gè)字節(jié)分配給3個(gè)Int類型關(guān)聯(lián)值,分別存儲(chǔ)了1,2,3, 第25個(gè)字節(jié)是0。

當(dāng)t=.test2時(shí),前面24個(gè)字節(jié)還是留給關(guān)聯(lián)值的,但是test2只有兩個(gè)關(guān)聯(lián)值,所以使用了前面16個(gè)字節(jié)分配給他的關(guān)聯(lián)值,此時(shí)17到24這8字節(jié)就空置,第25個(gè)字節(jié)是1。

...

最后當(dāng)t = test4 , 沒(méi)有關(guān)聯(lián)值,所以前面的字節(jié)都是0, 只有第25個(gè)字節(jié)是3

以此類推...

第25個(gè)字節(jié)其實(shí)完全可以看成一個(gè)辨識(shí)位,或者說(shuō)第25個(gè)字節(jié)就是枚舉的本質(zhì),通過(guò)不同值來(lái)區(qū)分不同case,只是因?yàn)橛辛岁P(guān)聯(lián)值,所以開(kāi)辟了更多的空間來(lái)存儲(chǔ)而已。

后面多余的字節(jié)都是為了內(nèi)存對(duì)齊,內(nèi)存對(duì)其相關(guān)的知識(shí)大家可以自行上網(wǎng)查閱。

補(bǔ)充:

既然說(shuō)到了關(guān)聯(lián)值,那就順便對(duì)枚舉原始值說(shuō)兩句。具通過(guò)你打印帶原始值的枚舉的內(nèi)存數(shù)據(jù),發(fā)現(xiàn)是否帶有原始值對(duì)枚舉的內(nèi)存占用并無(wú)影響,所以原始值應(yīng)該不是存儲(chǔ)在枚舉變量的內(nèi)部的。大家可以自己試驗(yàn)一下

總結(jié)

到此這篇關(guān)于深入理解Swift枚舉關(guān)聯(lián)值內(nèi)存的文章就介紹到這了,更多相關(guān)Swift枚舉關(guān)聯(lián)值的內(nèi)存內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Swift中通知中心(NotificationCenter)的使用示例

    Swift中通知中心(NotificationCenter)的使用示例

    這篇文章主要給大家介紹了關(guān)于Swift中通知中心(NotificationCenter)使用的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2017-10-10
  • Swift圖像處理之優(yōu)化照片

    Swift圖像處理之優(yōu)化照片

    Core Image能通過(guò)分析圖片的各個(gè)屬性,人臉的區(qū)域等進(jìn)行自動(dòng)優(yōu)化圖片。我們只需要調(diào)用autoAdjustmentFiltersWithOptions這個(gè)API方法獲取各個(gè)自動(dòng)增強(qiáng)濾鏡來(lái)優(yōu)化圖片即可。不管是人物照片還是風(fēng)景照均可增強(qiáng)效果
    2015-11-11
  • Swift編程中的初始化與反初始化完全講解

    Swift編程中的初始化與反初始化完全講解

    這篇文章主要介紹了Swift編程中的初始化與反初始化完全講解,是Swift入門(mén)學(xué)習(xí)中的基礎(chǔ)知識(shí),需要的朋友可以參考下
    2015-11-11
  • Swift中用到extension的一些基本的擴(kuò)展功能講解

    Swift中用到extension的一些基本的擴(kuò)展功能講解

    這篇文章主要介紹了Swift的一些基本的擴(kuò)展功能,即extension關(guān)鍵字的使用,需要的朋友可以參考下
    2015-11-11
  • Swift中swift中的switch 語(yǔ)句

    Swift中swift中的switch 語(yǔ)句

    本文給大家介紹了swift中的swift語(yǔ)句,以及和c語(yǔ)音中的寫(xiě)法區(qū)別,本文介紹的非常詳細(xì),需要的朋友參考下
    2016-12-12
  • Swift使用WKWebView在iOS應(yīng)用中調(diào)用Web的方法詳解

    Swift使用WKWebView在iOS應(yīng)用中調(diào)用Web的方法詳解

    這篇文章主要介紹了Swift使用WKWebView在iOS應(yīng)用中調(diào)用Web的方法詳解,使用WKWebView便等于使用和Safari中相同的JavaScript解釋器,用來(lái)替代過(guò)去的UIWebView,需要的朋友可以參考下
    2016-04-04
  • Swift中defer關(guān)鍵字推遲執(zhí)行示例詳解

    Swift中defer關(guān)鍵字推遲執(zhí)行示例詳解

    這篇文章主要給大家介紹了關(guān)于Swift中defer關(guān)鍵字推遲執(zhí)行的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-03-03
  • SwiftUI圖片縮放、拼圖等處理教程

    SwiftUI圖片縮放、拼圖等處理教程

    SwiftUI是一種使用Swift語(yǔ)言在蘋(píng)果設(shè)備上構(gòu)建用戶界面的創(chuàng)新且簡(jiǎn)單的方式,下面這篇文章主要給大家介紹了關(guān)于SwiftUI圖片縮放、拼圖等處理的相關(guān)資料,需要的朋友可以參考下
    2021-08-08
  • Spring中BeanFactory與FactoryBean的區(qū)別解讀

    Spring中BeanFactory與FactoryBean的區(qū)別解讀

    這篇文章主要介紹了Spring中BeanFactory與FactoryBean的區(qū)別解讀,Java的BeanFactory是Spring框架中的一個(gè)接口,它是用來(lái)管理和創(chuàng)建對(duì)象的工廠接口,在Spring中,我們可以定義多個(gè)BeanFactory來(lái)管理不同的組件,需要的朋友可以參考下
    2023-12-12
  • Swift數(shù)組詳細(xì)用法解析

    Swift數(shù)組詳細(xì)用法解析

    這篇文章主要為大家詳細(xì)介紹了Swift數(shù)組詳細(xì)用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11

最新評(píng)論