一.对象方法的调用内存分布图
在oc中类是描述对象的抽象概念。简单的来说,类是用来描述对象的属性与方法的,也就是它具有什么特点,能做什么事等等。但是今天我给大家写的博客并不是来介绍什么是类,而是为大家解决类的属性、类的方法和类方法的调用在内存当中是怎么实现的。那么我们先用代码,然后再用图来为大家讲解。
{
NSString *_name;
int _age;
float _weight;
}
上面是属性的声明:
-(void)run;
-(void)eat;
上段代码是类方法的实现。那么我们来看看具体的类的属性、方法声明及方法的调用内存分布图吧。
如上图我们可以看出来,首先由于要创建一个对象,也就是说创建对象的时候:1)申请一块内存空间;2)给申请内存中的属性初始化(_name = null;_age = 0;_weight = 0);3)返回该空间的首地址。那么我们不难看出,申请空间的地方就是在堆区。然后由于返回的时候需要一个指针去接收地址,该地址也就是存在于栈区的指针,那么里面存的地址也就是堆区返回的地址了。
然后就是方法了,方法存在于代码区。那么我们具体来看看,创建对象后调用方法是怎么执行的。对象发出调用指令(*person)—>找到在堆区的isa指针—>找到代码区的相应的方法(run或者eat),然后再执行该方法。
二.类方法调用的内存分布图
1)普通的类方法调用
@interface Person:NSObject
-(void)run;
-(void)eat;
@end
下面代码是调用方法:
[Person run];
[Person eat];
这就是累方法的直接的调用,那么我们来看看图,然后具体是怎么分布的我将为大家解答。
由图我们不难看出,当类方法直接通过类名调用方法的时候,由于不需要创建对象,那么类名是直接通过去代码区寻找相应的方法,从而实现自己调用方法的目的。这样的方法用起来很方便,但是也是有缺点的,是什么呢?如果你要访问实例变量怎么访问呢?因为不在内存开辟空间创建对象,那么类方法也没法在方法的实现的内部直接访问了,这就是不同于对象方法,也可以说是一个缺陷吧。当然后面还是有想法可以访问的,我这里就不多说了。
2)匿名类方法的调用
[Car new]
NSLog(@"%d",[Car new]->_xxxxx);
我们来看下内存的分布图:
三.组合方法在内存中的分布及其调用
@interface Dog:NSObject
-(void)eat;
-(void)run;
@end
上面写的代码是一个Dog的方法的声明。
@interface Person:NSObject
{
NSString *_name;
Dog *_dog;
}
@end
人类的声明,并且我们可以知道人的属性里面有个Dog的属性,这是他们两个能连起来的重点。我们直接来看内存分布图吧。