iOS alloc&init探索

1.alloc 探索

创建一个NSObject对象 LGPerson

    LGPerson *p1 = [LGPerson alloc];

    LGPerson *p2 = [p1 init];

    LGPerson *p3 = [p1 init];

    LGNSLog(@"%@ - %p",p1,&p1);

    LGNSLog(@"%@ - %p",p1,&p2);

    LGNSLog(@"%@ - %p",p1,&p3);

控制台打印输出:

<LGPerson: 0x600002208560> - 0x7ffee9a44118

<LGPerson: 0x600002208560> - 0x7ffee9a44110

<LGPerson: 0x600002208560> - 0x7ffee9a44108

现象 :可以看到打印出来的三个对象是同一个
p1,p2,p3的指针地址是不同的 但是他们指向的是同一片内存地址

2.alloc是怎么创建的?具体实现原理探究

这里有三种方式来找

(1)下断点 

    通过 control + in 找到objec_alloc

(2) 通过下符号断点,如果事先知道方法,直接下

objc_alloc,或者直接下alloc断点

 (3) 通过汇编方式  

libobjc.A.dylib`objc_alloc:

 

3.通过源码分析流程

看源码 下载+配置

拿到源码,全局搜索alloc {,可以找到alloc方法,然后进入

_objc_rootAlloc方法,一步一步走。

通过源码分析可以看出流程

 从上面的源码可以看出alloc方法开辟了内存,一个指针占用8个字节,这里提供里外一种二进制计算方式

    // (x + WORD_MASK)  >> 3 << 3

0000 1111 >> 3          0000 0001

0000 0001<<3           0000 1000  //8

对象需要内存空间  WORD_MASK 8的倍数 8字节对齐 同时if (size < 16) size = 16; 满足内存空间最小为16bytes

内存对齐:让CPU读取更加方便,用空间来换取时间

假设我们的内存快 字节方式补齐 如同4,5,6,7,8 读取就不方便

4.探索init,new方法

- (id)init {

    return _objc_rootInit(self);

}

id

_objc_rootInit(id obj)

{

    // In practice, it will be hard to rely on this function.

    // Many classes do not properly chain -init calls.

    return obj;

}

返回的就是alloc出来的obj。

init没做任何操作,一般在这里是工厂方式来重写方法,自定义,我们经常会这样写代码

- (instancetype)init{

    self = [super init];

    if (self) {

        

    }

    return self;

}

//

[super init] 重写父类的方法 防止覆盖父类的方法

self =  [super init]  

= 是确认继承父类 可以延伸自己的方法

if(self)做判断处理 防止父类在init的时候return nil 

做一个安全的处理 不然子类的实现就没有意义了

通过源码,看出new就是callAlloc+init的组合实现

+ (id)new {

    return [callAlloc(self, false/*checkNil*/) init];

}



猜你喜欢

转载自www.cnblogs.com/cui-cui/p/12057794.html