写在最前:记录一个最近看到的一个问题,实例对象是alloc创建的还是init创建的?写的不好,还请看到的人轻喷!
有一个Person
类,声明一个age
属性
Person *p = [Person alloc];
p.age = 10;
Person *p1 = [p init];
Person *p2 = [p init];
复制代码
首先有两个疑问: Q1: p1和p2是相同的吗? Q2: p1.age和p2.age的值是多少?(0或者10) 我们先来看一下结果Q1:
p1=<Person: 0x6000029bca80>
p2=<Person: 0x6000029bca80>
复制代码
通过其内存地址可以看到这两个对象是一样的(但是没存地址一样就足以证明这两个对象是同一个东西吗,这不一定,p1,p2在初始化的时候,初始化的内容可能不一样)
结果Q2:
p1.age=10
p2.age=10
复制代码
通过这个结果好像可以看出:
Person *p1 = [p init];
Person *p2 = [p init];
等价于
Person *p1 = p;
Person *p2 = p;
哦,似乎init方法没什么用啊?
复制代码
那我们就看一下alloc方法干了些什么 通过objc的NSObject代码:
1.
+ (id)alloc {
reeturn _objc_rootAlloc(self);
}
可知返回的这个self应该就是指当前的这个类对象
2.在进一步跟进去_objc_rootAlloc
id
_objc_rootAlloc(Class cls)
{
return callAlloc(cls, false/*chechNil*/, true/*allocWithZone*/);
}
3.跟进去callAlloc
static id callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
if (checkNil && !cls) return nil;
if (!cls->ISA()->hasCustomAWZ()) {
// No alloc/allocWithZone implementation. Go straight to the allocator.
// fixme store hasCustomAWZ in the non-meta class and
// add it to canAllocFast's summary
if (fastpath(cls->canAllocFast())) {
// No ctors, raw isa, etc. Go straight to the metal.
bool dtor = cls->hasCxxDtor();
id obj = (id)calloc(1, cls->bits.fastInstanceSize());
if (slowpath(!obj)) return callBadAllocHandler(cls);
obj->initInstanceIsa(cls, dtor);
return obj;
}
else {
// Has ctor or raw isa or something. Use the slower path.
id obj = class_createInstance(cls, 0);
if (slowpath(!obj)) return callBadAllocHandler(cls);
return obj;
}
}
// No shortcuts available.
if (allocWithZone) return [cls allocWithZone:nil];
return [cls alloc];
}
4.这里主要用到的代码就是id obj = class_createInstance(cls, 0);跟进去看到
id class_createInstance(Class cls, size_t extraBytes)
{
return _class_createInstanceFromZone(cls, extraBytes, nil);
}
5.继续跟进去_class_createInstanceFromZone
static id _class_createInstanceFromZone(Class cls, size_t extraBytes, void *zone,
bool cxxConstruct = true,
size_t *outAllocatedSize = nil)
{
if (!cls) return nil;// 首先是判断是否为空
assert(cls->isRealized());// 检查是否已经realize 了
// Read class's info bits all at once for performance
bool hasCxxCtor = cls->hasCxxCtor();
bool hasCxxDtor = cls->hasCxxDtor();
bool fast = cls->canAllocNonpointer();
size_t size = cls->instanceSize(extraBytes); // 这一步是获取对象大小的
if (outAllocatedSize) *outAllocatedSize = size;
id obj;
if (!zone && fast) {
obj = (id)calloc(1, size); // 分配空间
if (!obj) return nil;
obj->initInstanceIsa(cls, hasCxxDtor);// 初始化
}
else {
if (zone) {
obj = (id)malloc_zone_calloc ((malloc_zone_t *)zone, 1, size);
} else {
obj = (id)calloc(1, size);
}
if (!obj) return nil;
// Use raw pointer isa on the assumption that they might be
// doing something weird with the zone or RR.
obj->initIsa(cls);
}
if (cxxConstruct && hasCxxCtor) {
obj = _objc_constructOrFree(obj, cls);
}
return obj;
}
最主要的代码就是
obj = (id)calloc(1, size);
if (!obj) return nil;
obj->initInstanceIsa(cls, hasCxxDtor);
复制代码
事实上我们看不到苹果的源码,下面通过汇编代码来看一下(真机调试),首先在Person *p = [Person alloc];处打个断点,当运行到该断点时,在Xcode菜单栏-->Debug-->DebugWorkflow-->Always Show Disassembly选中,