談談Swift中的枚舉內存布局

在掘金上看到從 匯編 到 Swift 枚舉內存 的驚鴻一瞥之后,作者分析了幾種不同枚舉的內存布局丰嘉,但是我感覺覆蓋的不夠全面履羞,算是對作者那篇文章的一個補充。建議先看下作者的文章茂契,作者的結論如下:

關聯(lián)值枚舉:
最大字節(jié)數(shù)之和 額外 + 1
最后一個字節(jié) 存放 case 類型
非關聯(lián)值枚舉:
內存 占用 1個字節(jié)
內存中 以下標數(shù) 為值蝶桶,依次累加

疑問

不知道你看完之后,有沒有我同樣的疑問账嚎?

  1. 普通枚舉時莫瞬,內存占用一個字節(jié),而一個字節(jié)最多只能從0到255郭蕉,那么當case的選項超出256個時疼邀,會怎樣
  2. 若關聯(lián)值得類型是協(xié)議,結構體召锈,類或其他枚舉呢旁振?這個時候內存占用是怎么樣的
  3. 如果是遞歸枚舉呢?

答案

  • 普通枚舉,測試代碼和結果如下說明測試代碼中的show函數(shù)會打印涨岁,枚舉的地址拐袜,內存和大小,從復制Mems
func test(){
     enum TestEnum {
       case testCase1
       case testCase2
    }
   var testEnum = TestEnum.testCase1
   show(val: &testEnum)
   testEnum = .testCase2
   show(val: &testEnum)
}
image
  • 當case選項過多超出256個時梢薪,比如出現(xiàn)300個時蹬铺,會占用2個字節(jié),由于超出2個字節(jié)需要的case太多秉撇,我沒有進行測試甜攀,但應該是依次類推的
//測試case過多時
func test1(){
    var testEnum = MoreCaseEnum.case257
    show(val: &testEnum)
}
image
  • 當關聯(lián)值是結構體時秋泄,跟作者的結論一樣
struct TestStruct: TestProtocol {
    var testPropetry1 = 10
    var testPropetry2 = 11
    var testPropetry3 = 12
    var testPropetry4 = 13
    var testPropetry5 = 14
}
func test2() {
    enum TestStructEnum {
        case testCase1
        case testCase2(TestStruct)
        case testCase3
    }
    var testEnum = TestStructEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(TestStruct())
    show(val: &testEnum)
    testEnum = .testCase3
    show(val: &testEnum)
}
image
  • 當關聯(lián)值是class時,跟作者的結論不一樣,測試代碼和結果如下
    結論:枚舉一共占用了8個字節(jié)规阀,若是關聯(lián)class的case恒序,則存放對象的地址,其他的按照case的順序賦值谁撼,此時是按照2*index賦值的歧胁,index為第幾個無關聯(lián)值的case
//測試關聯(lián)值的類型是class
func test3() {
    enum TestClassEnum {
        case testCase1
        case testCase2(TestClass)
        case testCase3
    }
    var testEnum = TestClassEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(TestClass())
    show(val: &testEnum)
    testEnum = .testCase3
    show(val: &testEnum)
}
image
  • 當關聯(lián)值的類型class+bool(這里換成其他小于4個字節(jié)l的類型都一樣,比如Int16厉碟,Int8)時
    結論:枚舉占用8字節(jié)喊巍,當關聯(lián)值是對象是,存放的是對象的地址墨榄,否則玄糟,8字節(jié)的前半部分存放的是區(qū)分類型,后半部分存放的關聯(lián)的值或者枚舉的case的位置(具體的規(guī)則我沒測出來)
func test4() {
    enum TestClassOtherEnum {
        case testCase1
        case testCase2(TestClass)
        case testCase3(Bool)
    }
    var testEnum = TestClassOtherEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(TestClass())
    show(val: &testEnum)
    testEnum = .testCase3(true)
    show(val: &testEnum)
}
image
  • 關聯(lián)值的類型是占用一字節(jié)的類型時袄秩,比如bool和其他無關聯(lián)值枚舉
    結論:枚舉占用一個字節(jié)阵翎,前4位區(qū)分類型,后四位來表示具體的值
func test5() {
    enum TestEnum {
        case testCase1
        case testCase2
    }
    enum TestSamllEnum {
        case testCase1
        case testCase2(TestEnum)
        case testCase3(Bool)
    }
    var testEnum = TestSamllEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(.testCase2)
    show(val: &testEnum)
    testEnum = .testCase3(true)
    show(val: &testEnum)
}
image
  • 關聯(lián)值的類型是協(xié)議時
    結論:枚舉占用40個字節(jié)之剧,最后一項是區(qū)分類型郭卫,對于關聯(lián)值協(xié)議的case,若滿足協(xié)議的是class時背稼,第一項是class的地址贰军,若滿足協(xié)議的是struct時,當struct的占用空間不大于24時蟹肘,則前三項存放的是結構體的值词疼,否則把結構體的值存放到外部
func test6() {
    enum TestProtocolEnum {
        case testCase1
        case testCase2(TestProtocol)
        case testCase3
    }
    var testEnum = TestProtocolEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(TestClass())
    show(val: &testEnum)
    testEnum = .testCase2(TestStruct())
    show(val: &testEnum)
    testEnum = .testCase3
    show(val: &testEnum)
}
image
  • 枚舉類型是遞歸枚舉時
    結論:此時占用空間一直是8
func test7() {
    indirect enum TestIndirectEnum {
        case testCase1
        case testCase2(TestIndirectEnum)
        case testCase3
    }
    var testEnum = TestIndirectEnum.testCase1
    show(val: &testEnum)
    testEnum = .testCase2(.testCase3)
    show(val: &testEnum)
    testEnum = .testCase3
    show(val: &testEnum)
}
image

Other

以上所有的結論都是測試并總結出來,不能保證絕對的正確性帘腹,僅供參考,測試demo

參考鏈接

?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末贰盗,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子阳欲,更是在濱河造成了極大的恐慌舵盈,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,214評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件球化,死亡現(xiàn)場離奇詭異秽晚,居然都是意外死亡,警方通過查閱死者的電腦和手機筒愚,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,307評論 2 382
  • 文/潘曉璐 我一進店門赴蝇,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人巢掺,你說我怎么就攤上這事句伶∩衷牛” “怎么了?”我有些...
    開封第一講書人閱讀 152,543評論 0 341
  • 文/不壞的土叔 我叫張陵熄阻,是天一觀的道長。 經(jīng)常有香客問我倔约,道長秃殉,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 55,221評論 1 279
  • 正文 為了忘掉前任浸剩,我火速辦了婚禮钾军,結果婚禮上,老公的妹妹穿的比我還像新娘绢要。我一直安慰自己吏恭,他們只是感情好,可當我...
    茶點故事閱讀 64,224評論 5 371
  • 文/花漫 我一把揭開白布重罪。 她就那樣靜靜地躺著樱哼,像睡著了一般。 火紅的嫁衣襯著肌膚如雪剿配。 梳的紋絲不亂的頭發(fā)上搅幅,一...
    開封第一講書人閱讀 49,007評論 1 284
  • 那天,我揣著相機與錄音呼胚,去河邊找鬼茄唐。 笑死,一個胖子當著我的面吹牛蝇更,可吹牛的內容都是我干的沪编。 我是一名探鬼主播,決...
    沈念sama閱讀 38,313評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼年扩,長吁一口氣:“原來是場噩夢啊……” “哼蚁廓!你這毒婦竟也來了?” 一聲冷哼從身側響起常遂,我...
    開封第一講書人閱讀 36,956評論 0 259
  • 序言:老撾萬榮一對情侶失蹤纳令,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后克胳,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體平绩,經(jīng)...
    沈念sama閱讀 43,441評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 35,925評論 2 323
  • 正文 我和宋清朗相戀三年漠另,在試婚紗的時候發(fā)現(xiàn)自己被綠了捏雌。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,018評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡笆搓,死狀恐怖性湿,靈堂內的尸體忽然破棺而出纬傲,到底是詐尸還是另有隱情,我是刑警寧澤肤频,帶...
    沈念sama閱讀 33,685評論 4 322
  • 正文 年R本政府宣布叹括,位于F島的核電站,受9級特大地震影響宵荒,放射性物質發(fā)生泄漏汁雷。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,234評論 3 307
  • 文/蒙蒙 一报咳、第九天 我趴在偏房一處隱蔽的房頂上張望侠讯。 院中可真熱鬧,春花似錦暑刃、人聲如沸厢漩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,240評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽溜嗜。三九已至,卻和暖如春架谎,著一層夾襖步出監(jiān)牢的瞬間粱胜,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,464評論 1 261
  • 我被黑心中介騙來泰國打工狐树, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留焙压,地道東北人。 一個月前我還...
    沈念sama閱讀 45,467評論 2 352
  • 正文 我出身青樓抑钟,卻偏偏與公主長得像涯曲,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子在塔,可洞房花燭夜當晚...
    茶點故事閱讀 42,762評論 2 345

推薦閱讀更多精彩內容