iOS大师班01 - alloc浅析

知道中国最著名的女程序员是谁么?----- 宋丹丹!程序员

至于为啥看看下面这组图你就知道了算法

放错了,是下面这组app

在2000年手机才刚刚普及的时候,就提出了这么言简意赅的跨时代结论,中国最著名的女程序员除了宋丹丹的还有谁!?iphone

ps:乔布斯他就是个买手机的,他懂个锤子的iphone!!!函数

首先话很少,为了证实宋丹丹所言非虚,一张流程图足以说明一切:ui

若是看着有点晕,画出路线图atom

那么此次来咱们就看看宋丹丹的“三个思想”中的前两个吧。spa

1. 瞅瞅你对象占多大地方 --- instanceSize(size_t extraBytes)

1.1 aligned

曹冲曾说过"大象拉么大,一个冰箱装不下”,绝大多数大象都不是一个冰箱能装下的,那就把大象切了分开多装几个冰箱呗。翻译

下面小学3年级的最后一道应用题:3d

已知,每一个冰箱10平方米,一个大象19平方米。问这个大象装进冰箱后占多少平方米?

解:19 ÷ 10 = 1....9(平方米)

∵ 根据题意,大象应该装2个冰箱

∴ 2 x 10 = 20(平方米)

答:大象装进冰箱后占20平方米。

问题是电脑可不知道啥“根据题意”,因此他的算法是:

19 + 10 = 29

而后他再把个位数给抹去

获得20

这个方法有个弊端<冰箱的大小必定至少要是进制的n幂>,若是十进制,冰箱大小必定要是10,100,1000..... 由于CPU是64位,64/8=8,因此CPU用的是8进制。同理若是是32位则用的是4进制。

这个过程被称为<字节对齐>,翻译成英文就是<aligned>,下面就是这个方法的实现

# define WORD_MASK 7UL
static inline uint32_t word_align(uint32_t x) {
    return (x + WORD_MASK) & ~WORD_MASK;
}
复制代码

WORD_MASK = 7,7在2进制中等于8

这里WORD_MASK就是冰箱大小,x就是大象大小,&~WORD_MASK至关于抹去零头。

1.2 extra

ps: extra也能够翻译成益达,没错就是那个口香糖。

一头大象还好,但是我们的app不可能只alloc一个大象吧。因此为了方便管理,每一个大象装箱的时候第一个冰箱就放入一个这个大象的档案袋(<isa>),而不是大象自己。

为了防止一个装箱失误,因此规定就算这个大象就算他啥都没有(nill),也要给他留个位置。 因此一个大象至少要占2个冰箱的位置(2*8)16平方米。

有些大象可能还有些特殊状况要额外天占用一些空间。下面就是这个方法的实现

size_t instanceSize(size_t extraBytes) {
        size_t size = alignedInstanceSize() + extraBytes;
        if (size < 16) size = 16;
        return size;
    }

uint32_t alignedInstanceSize() {
        return word_align(unalignedInstanceSize());
    }
复制代码

<unalignedInstanceSize>就是从档案袋里读取大象数据

uint32_t unalignedInstanceSize() {
        assert(isRealized());
        return data()->ro->instanceSize;
    }
复制代码

如今你把“大象”换成“对象”,“平方米”换成“字节”,是否是很奇妙?

2. 给你对象腾地儿 --- calloc(size_t __count, size_t __size)

2.1 calloc

腾地儿自己没啥好说的,calloc本是就是库中的最基本函数。在内存的动态存储区中分配num个长度为size的连续空间。num:对象个数,size:对象占据的内存字节数。可是要注意的是

calloc在动态分配完内存后,自动初始化该内存空间为零,而malloc不作初始化,分配到的空间中的数据是随机数据。

size就是咱们上边算出来的大小

2.2 具体分配

虽然咱们如今知道了cpu是把大象分别放进多个冰箱里,可是如何分配呢?其实想一想也很简单,cpu并不会傻到把大象剁成肉臊子,而是把它按照部件一块一块而后分别放入冰箱中(毕竟后面还要注入灵魂)。 下面就来证明一下

首先建立一个大象类:

@interface Elephant : NSObject

@property (nonatomic, strong) NSObject *noise;
@property (nonatomic, assign) int head;
@property (nonatomic, copy)   NSString *body;
@property (nonatomic, assign) int tail;
@property (nonatomic, assign) int legs;

@end
复制代码

而后建立而且赋值

- (void)viewDidLoad {
    [super viewDidLoad];
    Elephant *wildElephant = [[Elephant alloc] init];
    wildElephant.noise = [NSObject new];
    wildElephant.head = 10;
    wildElephant.body = @"bigBody";
    wildElephant.tail = 20;
    wildElephant.legs = 50;
    NSLog(@"%@", wildElephant);
}
复制代码

咱们来看看手机是怎么存储的

第一个 0x0010d800100003dd5 就是咱们所说的isa,占了整整一个冰箱,彻底如咱们所料。

第二个 0x0000001400000000a 这是两个小部件(tail 和 head),由于是int类型(占4字节)就放到了一个冰箱里。

第三个 0x00000000000000032 这个是腿,也是小部件,可是没有能够“凑整”的了,因此虽然小可是仍是占了一个冰箱。

第四个 0x00006000000109d0 这个就是大部件了,单独放到一个冰箱里。

第五个 0x0000000010002018 同第四个。

由此咱们能够看出来calloc的分配空间仍是很合理的。

下回分解

白云大妈竟是程序先知,黑土大爷真的一脸懵逼?

注入灵魂究竟从何而来,次幕后是否还另有其人?

敬请期待下回分解。

彩蛋

原本想用《汉尼拔》的人体标原本描述对齐过程的,可是考虑到配图和你们的心理承受你能力就算了。

相关文章
相关标签/搜索