★ iOS高级:Swift入门精讲③ 01 swift编程-05-枚举-04原始值内存分布

前言:

本篇仅为视频学习笔记

短接上篇:
★ iOS高级:Swift入门精讲③ 01 swift编程-04-枚举-03关联值内存分布


 enum Season {
     case spring, summer, autumn, winter
 }

那么,这个家伙又占多大呢?这个时候我们来看一下:


注意看,打印出来的结果为:1、1、1,也就是说,到时候,我定义一个Season的枚举变量,它只占一个字节。

var s = Season.spring

思考一下,为什么只占一个字节就够了。原因,你这个枚举特别的简单,那到时候,我存储在内存中,你不觉得我用一个字节就能表示清楚你存储的是spring、是summer、是autumn、是winter吗?

举个例子,比如说它底层呢?给它编一个号倒时候存储内存的时候把spring当作0,那么这个summer当作是1,autumn当作是2,这个winter当作是3,也就是说到时候,s这一个字节内存里面,存储的就是这4个数字,要么存储0,要么存储1,要么存储2,要么存储3。思考一下,是不是就能表达枚举的真实内容呢?所以,这个很好理解。一个字节就够了。

一个s字节就能表示清楚是 case spring, summer, autumn, winter 这四个中的哪一个。var s = Season.spring底层用一个字节就可以搞定了。因为你取值范围就4个而已,只是存储4个值,你用一个字节不就搞定了吗?

你的值,也不是非常非常大的, case spring = 23232323,你才可能用8个字节来存储。

下面为整体代码:

  enum Season {
      case spring, summer, autumn, winter
  }
  
   var s = Season.spring
  MemoryLayout<Season>.size        // 1,实际用到的空间大小
  MemoryLayout<Season>.stride      // 1,分配占用的空间大小
  MemoryLayout<Season>.alignment   // 1,对齐参数

★ 如果改成下面这样打印出来的还是1

 enum Season: Int {
    case spring = 1, summer, autumn, winter
}

   var s = Season.spring

MemoryLayout<Season>.size        // 1,实际用到的空间大小
MemoryLayout<Season>.stride      // 1,分配占用的空间大小
MemoryLayout<Season>.alignment   // 1,对齐参数

为什么呢?这就是关联值、和原始值的一个区别:

关联值

如上面这个,叫做关联值。相当于我number这个成员,是跟具体的其它类型(Int,Int,Int,Int) 关联在一起存储的。这个叫关联值。

下面这个呢,叫做原始值


原始值

也就是我们在定义成员的时候,就给它搞一个默认的家伙,跟它关联在一起,有种这样的感觉,就是预先关联在一起。

★ 那么,它们(关联值、原始值) 本质有什么区别呢?
其实区别,非常非常简单,如果是关联值case number(Int,Int,Int,Int),是将你传进来的这个关联的值,直接存储到枚举变量的内存里面。如下:

var pwd = Password.number(5, 6, 4, 7)

是将传进来的5, 6, 4, 7存储在了变量pwd里面。这种东西叫做关联值,关联值是什么,是可以传进不同的值进来。也就是说,有一天我定义一个新的枚举变量,是不是我可以传不同的值啊。如下:

var pwd1 = Password.number(2, 4, 13, 0)  // 占用32字节
var pwd2 = Password.number(23, 43, 133,30)  // 占用32字节

所以,你想一想,既然这个关联值,是以后可以传入不同的值的,那不就意味着什么?意味着每一个枚举变量,有自己的内存去存储(23, 43, 133,30) 这些值啊。总体来说,这个关联值是由外面传进来的,而且,每次传的可能不一样,所以每一个枚举变量要有单独的内存去存储这些关联值(23, 43, 133,30) 。所以,关联值的特点是什么?是将传进来的这些关联值(23, 43, 133,30),直接存储到我们枚举变量pwd2的内存当中。

所以,你这个枚举变量是关联值的话,你的内存绝对跟将来要存储的关联值大小有关的。

接下来,再看一下原始值,原始值是固定死的。如下:

 enum Season: Int {
     case spring = 1, summer = 2, autumn = 3, winter = 4
 }

思考一下,上面这种东西 = 1叫做原始值,原始值是什么意思呢?它会跟你的成员永远绑定在一起,比如说spring以后就是1 ,summer以后就是2 ,autumn以后就是3 ,winter以后就是4。

说白了,它是不允许我们这个spring以后再传一个19,再传一个20绑定在一起。这是不允许的。如下:

 var s = Season.spring(19)

也就是,说白了,如下:

 var s = Season.spring
 
 var s1 = Season.spring
 
 var s2 = Season.spring

这个三个枚举变量都是全新的枚举变量吗?大家都是spring,但是我告诉你这三个的原始值都是1.不允许你自定义。但是如果我们的case number(Int,Int,Int,Int) 是一个关联值的话,那么每一个枚举成员都是可以传值的。所以,像这种情况,你的关联值肯定存储在枚举变量的内存里面。

但是,这个原始值就不一样了,原始值这个东西是固定死的。 case spring = 1, summer = 2, autumn = 3, winter = 4。

思考一下,既然原始值这个东西是固定死的,那么你觉得有必要这莫做吗?举个例子:

 enum Season: String {
     case spring = "1", summer = "2", autumn = "3", winter = "4"
 }
 
 var s = Season.spring
 
 var s1 = Season.spring
 
 var s2 = Season.spring
 
 MemoryLayout<Season>.size        // 1,实际用到的空间大小
 MemoryLayout<Season>.stride      // 1,分配占用的空间大小
 MemoryLayout<Season>.alignment   // 1,对齐参数

先说清楚String类型占用16个字节,那么有的人就会异想天开,既然spring原始值是1这个字符串,是不是1这个字符串,到时候会存储到枚举变量里面嘛?如果按照这个思路,去思考问题。

那么,刚才说过,1个字符串占用16个字节,那你想把这个字符串存到枚举变量,那你的意思不就是说,到时候,我定义一个Season.spring,赋值给这个枚举变量s,你的意思是,到时候s这个枚举变量,它里面存储的1,占用16个字节。到时候,又来一个Season.spring,这个s1这个枚举变量存储的是1,也占用16个字节。依次如下。你觉得有必要吗?大家s\s1\s2对应的原始值是固定死的。都是字符串1。你干嘛,把这个大家公共的都是1的这个家伙,存储到枚举变量里面去呢?没有这个必要。

你真正想拿到枚举值,直接s2.rawValue拿到这个值就好了。也就是说它真正底层存储,不像大家想象的这么浪费。如果你是这么想的,它是将字符串1存到这个s变量里面去,那就说明这个真是浪费内存,编译器是没有这么傻的。

那么,编译器怎么做呢?还是按照我刚刚的做法,尽管 enum Season: String这里面写了一个String,代表你的原始值是字符串类型,但是它依然是给 case spring = "1", summer = "2", autumn = "3", winter = "4"这些家伙标记一个序号来存储的。相当于这个spring 标记为0,autumn标为1,autumn标为2,winter标为3。也就是说,s\s1\s2这三个枚举变量都各占1个字节。

那么,这个s这1个字节里面其实存储的就是0这个值,因为我说了spring你可以把它当作0,但它究竟是从0开始,还是从1开始,到时候,我们窥探内存才知道。现在,我们假设从0开始。

好,那么我们定义s1 这个变量,它也只占1个字节,而且,这个字节里存储的值其实就是0。s2也是相同。那么这三个枚举变量,其实都占一个值。它只占一个字节。如果你想拿到对应的字符串,你可以s2.rawValue就可以了。


★ 原始值是不会,存储到枚举变量里面的,只有关联值会。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,233评论 6 495
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,357评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,831评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,313评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,417评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,470评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,482评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,265评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,708评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,997评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,176评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,827评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,503评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,150评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,391评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,034评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,063评论 2 352

推荐阅读更多精彩内容