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

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

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

這是枚舉最基礎(chǔ)的用法,但是在swift中,對枚舉的功能進行了加強,也就是關(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)建一個枚舉值t的時候,設(shè)置他的選項為test1,同時可以關(guān)聯(lián)3個Int類型的值,然后在switch中,我們還可以把這3個Int值取出來進行使用。

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

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

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

// 輸出 8 8 8 

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

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

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

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

enum Season {
 case Spring, Summer, Autumn, Winter
}
print("實際占用:",MemoryLayout<Season>.size)
print("分配:",MemoryLayout<Season>.stride)
print("對齊參數(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ù),這樣我們就不用每次拿到地址再去工具中看了

實際占用: 1
分配: 1
對齊參數(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

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

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

enum Test {
 case test1(v1: Int, v2: Int, v3: Int)
 case test2(v1: Int, v2: Int)
 case test3(v1: Int)
 case test4
}
 
print("實際占用:",MemoryLayout<Test>.size)
print("分配:",MemoryLayout<Test>.stride)
print("對齊參數(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))

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

實際占用: 25
分配: 32
對齊參數(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

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

但是通過這一個例子其實可能還看不出有什么規(guī)律,大家可以多用幾個例子來驗證,這是我就直接說結(jié)論了。

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

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

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

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

...

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

以此類推...

第25個字節(jié)其實完全可以看成一個辨識位,或者說第25個字節(jié)就是枚舉的本質(zhì),通過不同值來區(qū)分不同case,只是因為有了關(guān)聯(lián)值,所以開辟了更多的空間來存儲而已。

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

補充:

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

總結(jié)

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

相關(guān)文章

  • Swift初始化器與可選鏈的使用方法介紹

    Swift初始化器與可選鏈的使用方法介紹

    初始化器初始化是準備類、結(jié)構(gòu)或枚舉的實例以供使用的過程。此過程涉及為該實例上的每個存儲屬性設(shè)置初始值,并執(zhí)行在新實例準備就緒可供使用之前所需的任何其他設(shè)置或初始化,可選鏈是一種可以請求和調(diào)用屬性、方法和子腳本的過程,用于請求或調(diào)用的目標可能為nil
    2022-08-08
  • Swift在控件中添加點擊手勢的方法

    Swift在控件中添加點擊手勢的方法

    這篇文章主要介紹了Swift在控件中添加點擊手勢的方法,本文講解如何在tableview的headerview中添加點擊手勢的方法,需要的朋友可以參考下
    2015-01-01
  • swift中獲取字符串前綴的七種方法總結(jié)

    swift中獲取字符串前綴的七種方法總結(jié)

    在日常的開發(fā)中,經(jīng)常會需要獲取一個字符串的前綴,在這篇文章中我總結(jié)了在 Swift 中檢查字符串前綴的多種方法分享給大家,看看有沒有你不知道的
    2023-12-12
  • 解析Swift語言面相對象編程中的繼承特性

    解析Swift語言面相對象編程中的繼承特性

    這篇文章主要介紹了解析Swift語言面相對象編程中的繼承特性,是Swift入門學習中的基礎(chǔ)知識,需要的朋友可以參考下
    2015-11-11
  • swift 3.0中realm封裝類示例代碼

    swift 3.0中realm封裝類示例代碼

    這篇文章主要給大家介紹了關(guān)于swift 3.0中realm封裝類的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家學習或者使用swift具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧。
    2017-10-10
  • Swift編程之枚舉類型詳解

    Swift編程之枚舉類型詳解

    這篇文章主要介紹了Swift編程之枚舉類型,講解了枚舉語法、匹配枚舉值與switch語句、關(guān)聯(lián)值、原始值等內(nèi)容,Swift中枚舉類型是最重要的類型,感興趣的小伙伴們可以參考一下
    2016-02-02
  • 詳解Swift?中的幻象類型

    詳解Swift?中的幻象類型

    讓我們來看看一種技術(shù),它可以讓我們利用?Swift?的類型系統(tǒng)在編譯時執(zhí)行更多種類的數(shù)據(jù)驗證消除更多潛在的歧義來源,并幫助我們在整個代碼庫中保持類型安全,通過使用幻象類型(phantom?types),對Swift?幻象類型相關(guān)知識感興趣的朋友一起看看吧
    2022-05-05
  • swift如何利用系統(tǒng)庫將漢字轉(zhuǎn)換為拼音詳解

    swift如何利用系統(tǒng)庫將漢字轉(zhuǎn)換為拼音詳解

    將漢字轉(zhuǎn)換為拼音更利于我們大家開發(fā)搜索功能,所以這篇文章主要給大家介紹了關(guān)于swift如何利用系統(tǒng)庫將漢字轉(zhuǎn)換為拼音的相關(guān)資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-10-10
  • Swift3.0 GCD定時器的使用DEMO

    Swift3.0 GCD定時器的使用DEMO

    這篇文章主要介紹了Swift3.0 GCD定時器的使用,實現(xiàn)倒計時,UIDatePicker的使用, 仿寫一個活動倒計時的DEMO,需要的朋友可以參考下
    2017-02-02
  • swift在IOS應(yīng)用圖標上添加提醒個數(shù)的方法

    swift在IOS應(yīng)用圖標上添加提醒個數(shù)的方法

    本文是通過swift語言實現(xiàn)在應(yīng)用圖標右上角添加消息個數(shù)提醒的功能,非常不錯,具有參考借鑒價值,感興趣的朋友一起看下吧
    2016-08-08

最新評論

通山县| 松溪县| 长宁区| 安西县| 桐城市| 荆州市| 永昌县| 玛沁县| 中宁县| 武山县| 博乐市| 高清| 张掖市| 石棉县| 富民县| 安乡县| 浙江省| 赤城县| 攀枝花市| 华宁县| 阳朔县| 乐清市| 鄂托克前旗| 舞阳县| 旌德县| 衡水市| 崇阳县| 吉木乃县| 乡城县| 依安县| 曲松县| 贺州市| 定兴县| 遂川县| 车险| 资溪县| 镇原县| 东辽县| 桃源县| 大关县| 兴隆县|