内存中的五大区域.
一、栈区
又称 堆栈 ,由编译器自动分配释放,是用户存放程序临时创建的 局部变量 ,也就是说我们函数括弧“{}” 中定义的变量(但不包括 static 声明的变量, static 意味着在数据段中存放变量)。除此以外, 在函数被调用时,其参数也会被压入发起调用的进程栈中,并且待到调用结束后,函数的返回值 也会被存放回栈中。
由于 栈 的后进先出特点,所以 栈 特别方便用来保存/恢复调用现场。从这个意义上讲,我们可以把 堆栈 看成一个寄存、交换临时数据的内存区。
栈的地址空间在iOS中是以0X7开头
- 栈 是向低地址扩展的数据结构,是一块连续的内存区域
二、堆区
用于存放进程运行中被 动态分配 的内存段,堆区的大小并不固定,可动态扩张或缩减。当进程调用 alloc 等函数分配内存时,新分配的内存就被动态添加到堆上(堆被扩张);当利用 realse 释放内存时,被释放的内存从堆中被剔除(堆被缩减)。如果应用程序没有释放掉,操作系统会自动回收。变量通过 new、alloc、malloc、realloc 申请分配的内存块就存放在堆区。
- 由程序员分配释放,分配方式类似于链表,是向高地址扩展的数据结构,是不连续的内存区域。
三、全局/静态区
全局/静态区 是存放 全局变量 和 静态变量 的。
已初始化的全局变量和静态变量存放在一块区域。data段
未初始化的全局变量和静态变量在相邻的另一块区域。BSS段
由 static 修饰的变量会成为静态变量,该变量的内存由全局/静态区在 编译阶段 完成分配,且仅分配一次。
static 可以修饰局部变量也可以修饰全局变量。
- 全局/静态区 的内存在编译阶段完成分配,程序运行时会一直存在内存中,只有当程序结束后才会由操作系统释放。
四、常量区 -- 数据段
常量区 是一块比较特殊的存储区,常量区里面存放的是 常量 ,常量字符串就存放在常量区。
- 常量区 的内存在 编译阶段 完成分配,程序运行时会一直存在内存中,只有当程序结束后才会由操作系统释放。
五、代码区 -- 代码段
代码区 是用来存放 可执行文件的操作指令(存放函数的二进制代码),其实就是存放程序的所有代码。代码区 需要防止在运行时被非法修改,所以只准许读取操作,而不允许写入(修改)操作——它是不可写的。
什么叫做类加载呢?
我们可以想象,在创建对象的时候,肯定是需要访问类的,声明一个类的指针变量也会访问类的。
当程序运行期间,当某个类第一次被访问到的时候,会将这个类存储到内存中的代码段区域,这个过程就叫做类加载。
只有类在第一次被访问的时候,才会做类加载。
一旦类被加载到代码段以后,直到程序结束的时候才会被释放。
对象在内存中如何存储的
假设下面这句代码写在函数之中:
Person *p1 = [Person new];
Person *p1 会在栈内存中申请一个空间,在栈内存中声明一个Person类型的指针变量p1。p1是一个指针变量,那么只能存储地址。
[Person new],真正在内存中创建对象的其实是这句代码。
new做的事情,
- 第一是在堆内存中申请1块合适大小的空间;
- 第二是在这个空间中根据类的模板创建对象,类模板中定义了什么属性,就把这些属性依次的声明在对象之中; 对象中还有另外一个属性,叫做isa,它是一个指针,这个指针指向这个对象所属的类在代码段中的地址;
- 第三是初始化对象的属性。如果属性的类型是基本数据类型,那么赋值为0,如果属性的类型是C语言的指针类型,那么就赋值为NULL,如果属性的类型是OC的类指针类型,那么就赋值为nil;
- 第四是返回对象的地址,将这个地址赋值给p1。
注意:
对象中只有属性,而没有方法。只有自己所属类的属性外加一个isa指针指向代码段中的类;
- 如何访问对象的属性
指针名(对象名)->属性名;
根据指针找到指针指向的对象,再找到对象中的属性来访问 - 如何调用方法
[指针名(对象名) 方法名];
先根据指针名找到对象,对象发现要调用方法,再根据对象的isa指针找到类,然后调用类里的方法
对象作为类的属性
为什么不把方法存储在对象中?
因为每一个对象的方法的代码实现都是一模一样的,没有必要为每一个对象都保存一个方法,这样的话就太浪费空间了,既然都一样,那么就保存一份就可以了。
对象的属性的默认值.
如果我们创建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]