iOS 简答题 -- 内存(I)


内存


  • Objective-C 如何对内存管理的,说说你的看法和解决方法?

  Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
1). 自动内存计数ARC:由Xcode自动在App编译阶段,在代码中添加内存管理代码。
2). 手动内存计数MRC:遵循内存谁申请、谁释放;谁添加,谁释放的原则。
3). 内存释放池Release Pool:把需要释放的内存统一放在一个池子中,当池子被抽干后(drain),池子中所有的内存空间也被自动释放掉。内存池的释放操作分为自动和手动。自动释放受runloop机制影响。

  • 堆和栈的区别?

  栈(Stack):当我们创建一个值类型,如结构体,系统将其存储在一个被称为栈的内存区域中,是由CPU直接管理和优化的。当一个函数声明一个变量,变量将存储在栈中,当函数调用完毕后栈会自动释放该变量。因此栈是非常易于管理的、有效的,由于是CPU直接控制,速度非常快。

  堆(Heap):当我们创建了一个引用类型,如类,系统将把类实例存储在一个被称为堆的内存区域中。系统使用堆来存储其他对象引用的数据。堆是一个大的内存池,系统可以从该池中请求并动态分配内存块。堆不会像栈一样自动释放对象,需要额外的工作来完成。这使得在堆中创建和删除数据比栈慢。




运行时


  • 当建立一个A类,创建它的分类A+,在A类中有一个方法- (void)test;,在分类A+中也有一个方法- (void)test;,在初始化A类的实例对象中,调用test方法,会调用哪个test方法?为什么?

解析:会调用分类A+中的test方法,这是因为分类在添加到类的方法列表中,我们方法列表会移动,腾出存储空间给分类添加到前面的地址空间。当调用这个方法时若分类有这个方法直接调用,它就不会再到原类中在去代调用这个方法。

  • [super class] 和 [self class] 的异同?

这里是大神针对[super class]和[self class]详细介绍。

解析: 当我们进行方法调用时,编译器会对_msgSend(其他的消息普通的用这个)、objc_msgSend_stret(结构体方法调用)、objc_msgSendSuper(message对一个类的supperClass发送消息时调用)、objc_msgSendSuper_stret(结构体方法调用)这几个方法中调用其中一个。
[super class] 底层会调用 objc_msgSendSuper()给父类发送消息。
[super class] 最终编译器转化成了 objc_msgSendSuper(struct objc_super *,SEL) ,其中


struct objc_super {
    /// Specifies an instance of a class.
    __unsafe_unretained _Nonnull id receiver;

    /// Specifies the particular superclass of the instance to message. 
#if !defined(__cplusplus)  &&  !__OBJC2__
    /* For compatibility with old objc-runtime.h header */
    __unsafe_unretained _Nonnull Class class;
#else
    __unsafe_unretained _Nonnull Class super_class;
#endif
    /* super_class is the first class to search */
};

objc_super 是一个结构体,内部有一个 receiver 实例,和一 个 Class super_class,指向了当前类的父类 Class ,通过这个父类可以直接的从父类里边开始查找方法,由于消息接收者还是当前类的实例对象 self, 最终如果在父类中没有找到class 这个方法,会在 Person 类的父类 NSObject 中去查找 class 方法,由于 NSObject 的 class 方法,调用的是 object_getClass(self) ,所以最终消息接收者为 student 实例对象,所以返回的还是 Student .



[self class] 在调用 class 方法时最终会调用这个方法并且返回值:

//在NSObject.mm文件中的NSObject类定义的方法中
Class object_getClass(id obj)
{
    if (obj) return obj->getIsa();  //返回当前对象的isa
    else return Nil;
}

  当我们调用[self class] 时候实际上编译器最终给我们转成 objc_msgSend(self,@selector(class)) , 消息的接收者是当前所在类的实例对象 , 这个时候就会去 self 所在类 Student 去查找 class 方法 , 如果当前类 Student 没有 class 会向Student 父类 Person 类找 class 方法, 如果 Person 类也没有找到 class 方法,最终会找到最顶级父类 NSObject 的 class 方法, 最终找到 NSObject 的 class 方法 ,并调用了object_getClass(self) ,由于消息接收者是 self 当前类实例对象, 所以最终 [self class]输出 Student。



1. Objective-C 如何对内存管理的,说说你的看法和解决方法?

答:Objective-C的内存管理主要有三种方式ARC(自动内存计数)、手动内存计数、内存池。
1). 自动内存计数ARC:由Xcode自动在App编译阶段,在代码中添加内存管理代码。
2). 手动内存计数MRC:遵循内存谁申请、谁释放;谁添加,谁释放的原则。
3). 内存释放池Release Pool:把需要释放的内存统一放在一个池子中,当池子被抽干后(drain),池子中所有的内存空间也被自动释放掉。内存池的释放操作分为自动和手动。自动释放受runloop机制影响。



``


你可能感兴趣的:(iOS 简答题 -- 内存(I))