OC基础-类的加载(三)

内存中的五大区域.

一、栈区

又称 堆栈 ,由编译器自动分配释放,是用户存放程序临时创建的 局部变量 ,也就是说我们函数括弧“{}” 中定义的变量(但不包括 static 声明的变量, static 意味着在数据段中存放变量)。除此以外, 在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值 也会被存放回栈中。
由于 栈 的后进先出特点,所以 栈 特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把 堆栈 看成一个寄存、交换临时数据的内存区。
栈的地址空间在iOS中是以0X7开头

  • 栈 是向低地址扩展的数据结构,是一块连续的内存区域

二、堆区

用于存放进程运行中被 动态分配 的内存段,堆区的大小并不固定,可动态扩张或缩减。当进程调用 alloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用 realse 释放内存时,被释放的内存从堆中被剔除(堆被缩减)。如果应用程序没有释放掉,操作系统会自动回收。变量通过 new、alloc、malloc、realloc 申请分配的内存块就存放在堆区。

  • 由程序员分配释放,分配方式类似于链表,是向高地址扩展的数据结构,是不连续的内存区域。

三、全局/静态区

全局/静态区 是存放 全局变量静态变量 的。
已初始化的全局变量和静态变量存放在一块区域。data段
未初始化的全局变量和静态变量在相邻的另一块区域。BSS段
由 static 修饰的变量会成为静态变量,该变量的内存由全局/静态区在 编译阶段 完成分配,且仅分配一次。
static 可以修饰局部变量也可以修饰全局变量。

  • 全局/静态区 的内存在编译阶段完成分配,程序运行时会一直存在内存中,只有当程序结束后才会由操作系统释放。

四、常量区 -- 数据段

常量区 是一块比较特殊的存储区,常量区里面存放的是 常量 ,常量字符串就存放在常量区。

  • 常量区 的内存在 编译阶段 完成分配,程序运行时会一直存在内存中,只有当程序结束后才会由操作系统释放。

五、代码区 -- 代码段

代码区 是用来存放 可执行文件的操作指令(存放函数的二进制代码),其实就是存放程序的所有代码。代码区 需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。

image.png

什么叫做类加载呢?

我们可以想象,在创建对象的时候,肯定是需要访问类的,声明一个类的指针变量也会访问类的。
当程序运行期间,当某个类第一次被访问到的时候,会将这个类存储到内存中的代码段区域,这个过程就叫做类加载。
只有类在第一次被访问的时候,才会做类加载。
一旦类被加载到代码段以后,直到程序结束的时候才会被释放。

对象在内存中如何存储的

假设下面这句代码写在函数之中:

Person *p1 = [Person new];

Person *p1 会在栈内存中申请一个空间,在栈内存中声明一个Person类型的指针变量p1。p1是一个指针变量,那么只能存储地址。

[Person new],真正在内存中创建对象的其实是这句代码。

new做的事情,

  • 第一是在堆内存中申请1块合适大小的空间;
  • 第二是在这个空间中根据类的模板创建对象,类模板中定义了什么属性,就把这些属性依次的声明在对象之中; 对象中还有另外一个属性,叫做isa,它是一个指针,这个指针指向这个对象所属的类在代码段中的地址;
  • 第三是初始化对象的属性。如果属性的类型是基本数据类型,那么赋值为0,如果属性的类型是C语言的指针类型,那么就赋值为NULL,如果属性的类型是OC的类指针类型,那么就赋值为nil;
  • 第四是返回对象的地址,将这个地址赋值给p1。

注意:
对象中只有属性,而没有方法。只有自己所属类的属性外加一个isa指针指向代码段中的类;

  • 如何访问对象的属性
    指针名(对象名)->属性名;
    根据指针找到指针指向的对象,再找到对象中的属性来访问
  • 如何调用方法
    [指针名(对象名) 方法名];
    先根据指针名找到对象,对象发现要调用方法,再根据对象的isa指针找到类,然后调用类里的方法

对象作为类的属性

image.png

为什么不把方法存储在对象中?

因为每一个对象的方法的代码实现都是一模一样的,没有必要为每一个对象都保存一个方法,这样的话就太浪费空间了,既然都一样,那么就保存一份就可以了。

对象的属性的默认值.

如果我们创建1个对象,没有为对象的属性赋值. 那么这个对象的属性是有值的.
如果属性的类型是基本数据类型 默认值是0
如果属性的类型是C指针类型 那么默认值是NULL
如果属性的类型是OC指针类型 那么默认值是nil

nil,Nil,NULL,NSNull,kCFNull 区别

  • Objective-C实例对象指针空值: NSSring *str = nil;
  • Nil 类对象指针空值: Class class = Nil;
  • NULL C指针空值: char *p = NULL; 宏 NULL等价于0
    只能作为指针变量的值,代表指针不指向内存中的任何一块空间.
  • NSNull 是一个Objective-C继承NSObject的类,多用于数组字典里面的空值
    kCFNull 是NSNull的单例 [NSNull null]

https://zhuanlan.zhihu.com/p/189975215

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • OC基础总结 重新回过头看这些基础知识,对许多知识点都有新的认识,拥有坚实的基础才能更快的成长。 OC内存管理 -...
    xx_cc阅读 2,736评论 1 21
  • OC对象的本质<一> OC对象的分类 OC对象可以分为三类,分别是实例对象,类对象,元类对象。 实例对象(inst...
    雪山飞狐_91ae阅读 2,538评论 3 5
  • 学习目标 1.【理解】对象在内存中的存储 2.【理解】nil和NULL 3.【了解】#pragma mark分组导...
    Hm丶阅读 486评论 0 3
  • 一、内存五大区域: 1.栈(存储局部变量) 2.堆(程序员手动申请的字节空间 malloc calloc real...
    懵圈de果果阅读 255评论 0 0
  • 这篇文章主要想深入介绍一下,对于 OC 中的类和对象的更深层理解。 分组导航标记 在 OC 中有一种特殊语法,可以...
    FutureEye阅读 713评论 0 1