对象、类、组合的方法调用的内存分布图

一.对象方法的调用内存分布图

        在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);
        我们来看下内存的分布图:
      由代码段我们不难看出,创建了两次对象。那么我们来看看内存分布图吧。由存在堆区的对象我们可以知道当创建一次的时候我们给对象中的属性直接赋值了,但是由于代码打印出结果的时候又创建了一个对象,此时的对象并没有赋值,也就是说如果此时打印出结果的话,只能是初始化的时候得值,也就是(_name = null;_age = 0;_weight = 0),此时这就是打印出的结果。这也就是匿名类在内存中调用方法的详解。

三.组合方法在内存中的分布及其调用

      前面我们介绍了对象、类方法在内存当中调用各自的方法时是怎么调用的。那么接下来我将为大家解答组合在内存当中是怎么调用的,这部分也是很多人容易迷糊的地方,我想通过自己的理解告诉大家,这部分到底是怎么工作的,也为大家排忧解难。首先看代码。
@interface Dog:NSObject

-(void)eat;
-(void)run;

@end
     上面写的代码是一个Dog的方法的声明。
@interface Person:NSObject
{
     NSString *_name;
     Dog *_dog;
}
@end
     人类的声明,并且我们可以知道人的属性里面有个Dog的属性,这是他们两个能连起来的重点。我们直接来看内存分布图吧。


      如上图,里面包括了创建对象,调用方法和怎么实现的方法的最后调用。我们来看看内存分布图。
      首先:Dog和PPerson都在堆区当中创建了一个对象,但是由于在Person中有dog这个对象,所以在人的属性里面就包括了dog,那么初始化,返回指针,我么都可以从图中看出,接下来我将为大家说明怎么实现Person喂食物,Dog吃东西的具体流程。
      Person发出喂狗吃东西这个指令(p)—>找到堆区中isa(0x200)指针—>代码区Person中寻找这个喂狗这个方法(-(void)foodDog)—>找到Person中存在的属性(_dog = 0x10)—>找到Dog在内存中创建的那块空间(d1 = 0x10)—>找到isa(0x100)这个指针—>通过isa指针找到在内存代码区中的Dog类—>找到eat的方法。这就是组合的关系,通过在Person中dog的属性找到最后dog吃东西的方法。还是比较简单的,希望我的知识能解答到你心中的疑问,有什么issue就直接给我留言,我们一起交流交流。谢谢!!!!


    





       


       




   


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值