栈区,堆区,BBS,数据段,代码段
内存管理范围
任何继承NSObject的类的对象,对基本数据类型无效,因为不在堆区。
因为只有堆区的内容,不被系统自动处理。
对象的引用计数器:retainCount
判断对象是否销毁的依据。
retain:计数器+1;
release:计数器-1;
retainCount消息:获得对象当前的引用计数器的数值
谁retain谁release
dealloc:对象的临终遗言,只需重写,重写了dealloc就必须写 [super dealloc],并放在代码的最后一句
MRC内存手动管理主要用于XCode4.1版本前
ARC内存自动管理 主要用于XCode4.2版本后
gc垃圾回收机制,应用在JAVA等语言中
将ARC项目变成MRC(手动内存管理):
1.点击项目名称——> 2.build setting——> 3.在搜索框里输入auto——> 4.将ARC的选项yes—>no
僵尸对象:所占内存已经被释放的对象
野指针:指向一片被释放的内存
内存泄露:程序结束了,还有对象没被释放仍占据着内存。
有个野指针,就有个僵尸对象。
对象被释放后,里面的内容还在,直至下次此空间被再次使用时才会初始化。
检测僵尸对象:target—>edit run—>enabie zombie objects
使用僵尸对象检测很耗资源,所以不建议使用,应采用避免使用僵尸对象的方法,即指针指向空( nil )
nil调用任何东西都不报错
僵尸对象不能通过retain复活
nil:给对象赋空值
Nil:给类对象赋空值
NULL:通用指针(泛指)
多个对象内存管理:对象调用另一个对象时,给另一个对象retain一次,因为指向了,所以计数器应加一,而此对象在销毁时应release,因为他不指向了,所以计数器应该减一,可写在dealloc里作为遗言来执行。
为了避免接收新对象时,原对象没有减一,应先release后retain,只是用一个指针做中间变量
为了避免对象名修改,以至于对同一个对象先减后加,应先if判断两次是否同一个地址
@property参数
按原子性
atomic:默认的,加锁,安全,效率低
nonatomic:不加锁,不安全,效率高(推荐用)
读写性
readwrite:即生成set方法,也生成get方法(默认)
readonly:只生成get方法
按set方法划分
assign(默认的):set方法里是直接赋值,作用在基本数据类型上
retain:先release旧值,再retain新值,用在对象上,并判断了两次是否是一个对象
copy:先release旧值,copy新值
@property(nonatomic,assign,setter=XXX :,getter=PPPP)int age;重写int age;的set与get方法,其中set方法名为:XXX,get方法名为PPPP,即使如此,点语法还是能自动找到属性的set与get方法并进行取值赋值
@class
关键字,简单的申明有这么一个类,所以会增加效率
如@class dog 告知有dog这个类,但不会包含dog这个类的所有文内容
在.h中尽量用@class在.m中用Import再次导入,可以避免死循环,如在狗中导入人,人中导入狗,进而造成人找狗,狗找人的死循环
循环retain问题:
对于两个类人和狗,人调用了狗,狗调用了人,则人会导致狗retain,狗导致人retain,当狗和人都release后,因为人牵着狗,狗指向人,都没有断,导致内存泄露。
解决:1.让其中一个人多release一次(违反内存管理规则)2.把其中一个retain改成assign
把retain改成assign后,会导致被指向的一方不retain,即只有一个指向另一个,不会导致两方互指的死循环。
堆区,BBS区,数据区,代码段的分配,由低地址到高地址
栈区分配由高地址到低地址
NSString可能存放在堆区(很少),也可能存放在数据段,引用计数器不为1(可能是一个非常非常非常大的值)
所以,不能用NSString的计数器值>0来判断循环!
自动释放池:用来自动释放对象的
好处:不需要关心对象释放的时间,不需要关心对象什么时候调用release
自动释放池释放的时间:自动释放池结束
原理:当自动释放池结束时,会向池子里面的对象发送一条release消息
使用:1.创建对象2.加入自动释放池
两种加入方法:1.[ 对象名 autorelease] ; 2. 创建时将 init 换成autorelease;
对于对象来说,release之后会先判断其值是否为1,若为1直接销毁而不是减1为0后销毁