/**
内存管理的总结"
1.
黄金法则:
谁开发谁释放,谁污染谁治理
2. 引用计数+1的操作: alloc, retain , copy
3. 引用计数-1的操作: release, autorelease
4. 开辟空间: alloc 销毁空间: dealloc
2. 引用计数+1的操作: alloc, retain , copy
3. 引用计数-1的操作: release, autorelease
4. 开辟空间: alloc 销毁空间: dealloc
*/
/**
// 增加的次数 > 减少的次数 -- 内存泄露(内存空间没有得到释放)
// 增加的次数 < 减少的次数 -- 过度释放
// 增加的次数 = 减少的次数 如果还继续访问,就会有野指针问题出现,此时要把指针置为nil;
// 增加的次数 > 减少的次数 -- 内存泄露(内存空间没有得到释放)
// 增加的次数 < 减少的次数 -- 过度释放
// 增加的次数 = 减少的次数 如果还继续访问,就会有野指针问题出现,此时要把指针置为nil;
*/
//内存管理机制有哪些
/*
1.垃圾回收机制 gc(Garbage Collection), 由系统管理内存,开发人员不需要写任何代码管理内存.但是垃圾回收机制在内存释放的时候不及时 (Java开发中一直使用的就是垃圾回收技术) ; OC 2.0之后支持垃圾回收,只用于PC端开发;java也支持垃圾回收.
2.MRC (Manual Reference Count) : 手动引用计数管理机制,需要手动的开辟内存,并且要手动的释放内存,都是通过代码形式来完成.
3.ARC (Automatic Reference Count) : 自动引用计数管理机制,只需要开辟内存,而内存释放的代码由系统来写, ARC是基于MRC的.
总结: MRC和ARC的内存管理方式都是和引用计数器相关;
*/
// 如何通过引用计数器管理内存?
/*
图中的行为 OC的操作 OC中的方法
开灯 生成对象 alloc
需要照明 持有对象 retain / copy
不需要照明 释放对象 release / autorelease
关灯 销毁对象 dealloc (检测到引用计数器为0时,自动走这个方法)
*/
1.垃圾回收机制 gc(Garbage Collection), 由系统管理内存,开发人员不需要写任何代码管理内存.但是垃圾回收机制在内存释放的时候不及时 (Java开发中一直使用的就是垃圾回收技术) ; OC 2.0之后支持垃圾回收,只用于PC端开发;java也支持垃圾回收.
2.MRC (Manual Reference Count) : 手动引用计数管理机制,需要手动的开辟内存,并且要手动的释放内存,都是通过代码形式来完成.
3.ARC (Automatic Reference Count) : 自动引用计数管理机制,只需要开辟内存,而内存释放的代码由系统来写, ARC是基于MRC的.
总结: MRC和ARC的内存管理方式都是和引用计数器相关;
*/
// 如何通过引用计数器管理内存?
/*
图中的行为 OC的操作 OC中的方法
开灯 生成对象 alloc
需要照明 持有对象 retain / copy
不需要照明 释放对象 release / autorelease
关灯 销毁对象 dealloc (检测到引用计数器为0时,自动走这个方法)
*/
// alloc的作用:
在堆区开辟内存空间,
并且让对象的引用计数由0到1
//
引用计数 retainCount
是属于NSObject的,继承自它的类都拥有这个方法(可以使用点语法)
- // 使用引用计数(retainCount) 要满足的条件: 1. 必须是OC对象 2. 必须在堆区,其他内存区域的引用计数都是无穷大的, %lu打印 18446744073709551615 ; %ld打印-1
// retain
让对象的引用计数+1
// release
让对象的引用计数-1
- 已经释放掉空间的对象就叫做僵尸对象,操纵僵尸对象会引起Crash // 野指针 : 指向僵尸对象的指针就是野指针
//
内存管理的最终目的是想把开辟的空间给回收掉,所以无论通过哪一个指针变量进行release减1操作,都可以
// stringWithFormat:
创建字符串英文字符小于一个数的时候在常量区,大于某一个数的时候在堆区
// stringWithFormat :
创建的字符串是汉字时就存在堆区
// autorelease
和 release
的区别
//
共同点:
都可以让对象的引用计数器减1
// 不同点 : release是立即让对象的引用计数器减1,而autorelease是在未来的某一时刻让对象的引用计数器减1
//! autorelease必须和自动释放池(@autoreleasepool)结合使用,如果没有自动释放池,就不会减1
;它是在出
离它最近的自动释放池时,对对象的引用计数减1操作
//
使用遍历构造器创建的对象,我们不需要对他管理内存(遍历构造器在创建的时候,在创建的时候,方法内部给这个对象添加了
autorelease 方法)
- // 数组,字典,集合在添加元素的时候,内部会对这个对象的引用计数做一次+1
- // 数组在销毁的时候,会对数组中的每一个元素做一次引用计数-1的操作 [array release]
- /**
谁alloc谁release,只要我们没有看到引用计数加1的过程,那么就不要做减1的操作
便利构造器创建的对象都不需要release
*/ - // 优化的思想: 当一个对象不再使用的时候立即把他释放掉,达到优化内存的目的
----------------------------------------------------------
//
工程环境默认是ARC,需要手动改为MRC环境,才能使用内存管理的相关方法
打开僵尸对象调试:(不打开的话,操作僵尸对象不会报错):
内存溢出与内存泄露:
- UTF-8字符集,一个汉字占三个字节,gbk字符集,一个汉字占两个字节,比如varchar(10)类型的字段,UTF-8的汉字,只能存3个,gbk字符集的汉字却能存5个
copy:不是任何对象都可以接收copy消息,只有接受了NSCopying协议的对象才能接收copy消息。
//
属性中对不可变对象的copy都是浅拷贝,对可变字符串的拷贝就是深拷贝;
- 浅拷贝: 拷贝的是指针(地址),并且让指针指向的对象引用计数+1
- 深拷贝: 新开辟一块内存,空间大小和原来对象大小相同,而且里面存储的数据也相同,此时没有影响到原来对象的引用计数