为什么要管理内存?内存管理原则
内存大的计算机,运行起来速度会快,所谓的速度会快,其实是因为应用程序运行时能够保证充足的内存。应用程序运行时随时随地都需要消耗内存,对象实例化的过程,就是给对象分配内存空间的过程。
计算机的内存空间都是相对固定的,不断给各种对象(应用程序)分配内存,内存总会有消耗光的时候,内存消耗光了,应用程序以及系统就不能正常运行了。因此,必须对那些不再需要的内存进行释放处理,让这些内存能够再利用。
应用程序运行,实际上是不断地进行内存分配与内存释放的过程,也就是内存管理。
如果忘记释放内存,部分内存空间就会在应用程序结束之前一直占用着,称为内存泄漏。忘记释放内存多次发生,则内存会像水桶漏水一样漏光。
内存释放的两种方法:
(1)自动回收:利用垃圾回收机制,将内存中不再使用的对象判断为垃圾,自动回收。
(2)手动回收:引用计数器机制(arc)。
引用计数器原理:
(1)使用alloc、new或者copy创建一个对象时,对象的引用计数器为1;
(2)每调用retain一次,计数器的值就增加1;
(3)每调用release一次,计数器的值就减少1;
(4)当对象的引用计数器值为0时,那么它将被销毁,其占用的内存被系统回收,系统会自动调用dealloc,销毁这个对象。
(5)通过调用retainCount,可获得当前的引用计数器值。
内存管理的原则:
(1)谁创建,谁释放。如果通过alloc、new或copy创建了一个对象,必须调用release或autorelease;
(2)谁retain,谁release。只要调用了retain,无论这个对象是如何生成的,都要调用release;
(3)一般来说,除了alloc、new或copy创建的对象,其他方法创建的对象都被声明了autorelease。
autorelease自动释放:
(1)对象执行autorelease时会将对象添加到自动释放池autorelease pool中;
(2)当自动释放池销毁时,所有对象会作release操作;
(3)autorelease实际上只是把release的调用延迟了;
(4)自动释放池存储于内存中的栈中遵循“先进后出”的原则,越是后面的对象越先被释放。
内存区域划分:
(1)栈区(stack):由编译器自动分配释放,存放函数的参数值,局部变量的值等,内存区域是连续的;
(2)堆区(heap):一般由程序员分配释放,分配方式类似于链表,是不连续的内存区域;
(3)全局区(static):初始化的全局变量和静态变量是在一块区域,未初始化的全局变量和静态变量在相邻的另一块区域,程序结束后自动释放;
(4)文字常量区:常量字符串放在这里,程序结束后自动释放;
(5)程序代码区:存放函数体的二进制代码。
copy和retain的区别:
(1)assign:setter方法直接赋值,不进行任何retain操作;
(2)copy :建立一个索引计数为1的对象,然后释放旧对象;
(3)retain:释放旧的对象,将旧对象的值赋予输入对象,再提高输入对象的索引计数为 1;
(4)retain 是指针拷贝, copy 是内容拷贝;
(5)copy 是创建一个新对象,retain 是创建一个指针,引用对象计数加一;
(6)copy属性标识两个对象内容相同,新的对象retain count为1, 与旧有对象引用计数无关,旧有对象没有变化。copy减少对象对上下文的依赖。
浅拷贝和深拷贝的区别:
浅拷贝就是对内存地址的复制,让目标对象指针和源对象指向同一片内存空间。
深拷贝是指拷贝对象的具体内容,而内存地址是自主分配的,拷贝结束之后,两个对象虽然存的值是相同的,但是内存地址不一样,两个对象也互不影响,互不干涉。