In real development, sometimes we use new to create an object, sometimes we use alloc to create an object, so what’s the difference between the two?

NSObject *obj1 = [NSObject alloc];
NSObject *obj2 = [[NSOBject alloc] init];
NSObject *obj3 = [NSObject new];
Copy the code

Through runtime source code analysis, we found that:

[NSObject alloc] Instead of calling the + alloc method, the objc_alloc method is called, and then the callAlloc method is called inside the method.

objc_alloc(Class cls)
{
    return callAlloc(cls, true/*checkNil*/.false/*allocWithZone*/);
}
Copy the code

[[NSObject alloc] init] The underlying objc_alloc_init method is called, and then the callAlloc method is called inside the method as follows:

objc_alloc_init(Class cls)
{
    return [callAlloc(cls, true/*checkNil*/.false/*allocWithZone*/) init];
}
Copy the code

[NSObject new] Instead of calling + new, objc_opt_new is called and callAlloc is called internally.

objc_opt_new(Class cls)
{
#if __OBJC2__
    /** #define fastPath (x) (__builtin_expect(bool(x), 1)) slowpath(x) tells the compiler that x is likely to be 0. Expect the compiler to optimize __builtin_expect((x),1) to indicate that the value of x is more likely to be true; __builtin_expect((x),0) indicates that the value of x is more likely to be false. * /
    if (fastpath(cls && ! cls->ISA() - >hasCustomCore())) {
        return [callAlloc(cls, false/*checkNil*/) init];
    }
#endif
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(new));
}
Copy the code

The internal method of callAlloc implements:

static ALWAYS_INLINE id
callAlloc(Class cls, bool checkNil, bool allocWithZone=false)
{
#if __OBJC2__
    if (slowpath(checkNil && ! cls))return nil;
    /** hasCustomAllocWithZone -- only classes that do not inherit from NSObject/NSProxy are true */
    if (fastpath(! cls->ISA() - >hasCustomAWZ())) {
        return _objc_rootAllocWithZone(cls, nil);
    }
#endif

    // No shortcuts available.
    if (allocWithZone) {
        return ((id(*)(id, SEL, struct _NSZone *))objc_msgSend)(cls, @selector(allocWithZone:), nil);
    }
    return ((id(*)(id, SEL))objc_msgSend)(cls, @selector(alloc));
}
Copy the code

So you can see that [NSObject New] ends up calling callAlloc relative to [NSObject alloc], but [NSObject New] implicitly calls init.

Take a look at the implementation of the init method:

- (id)init {
    return _objc_rootInit(self);
}

_objc_rootInit(id obj)
{
    return obj;
}
Copy the code

You can see that init doesn’t really do anything but return the caller.